B. Knights of a Polygonal Table
time limit per test
1 second
memory limit per test
256 megabytes
input
standard input
output
standard output
Unlike Knights of a Round Table, Knights of a Polygonal Table deprived of nobility and happy to kill each other. But each knight has some power and a knight can kill another knight if and only if his power is greater than the power of victim. However, even such a knight will torment his conscience, so he can kill no more than kk other knights. Also, each knight has some number of coins. After a kill, a knight can pick up all victim’s coins.
Now each knight ponders: how many coins he can have if only he kills other knights?
You should answer this question for each knight.
Input
The first line contains two integers nn and kk (1≤n≤105,0≤k≤min(n−1,10))(1≤n≤105,0≤k≤min(n−1,10)) — the number of knights and the number kk from the statement.
The second line contains nn integers p1,p2,…,pnp1,p2,…,pn (1≤pi≤109)(1≤pi≤109) — powers of the knights. All pipi are distinct.
The third line contains nn integers c1,c2,…,cnc1,c2,…,cn (0≤ci≤109)(0≤ci≤109) — the number of coins each knight has.
Output
Print nn integers — the maximum number of coins each knight can have it only he kills other knights.
Examples
input
Copy
4 2 4 5 9 7 1 2 11 33
output
Copy
1 3 46 36
input
Copy
5 1 1 2 3 4 5 1 2 3 4 5
output
Copy
1 3 5 7 9
input
Copy
1 0 2 3
output
Copy
3
Note
Consider the first example.
- The first knight is the weakest, so he can’t kill anyone. That leaves him with the only coin he initially has.
- The second knight can kill the first knight and add his coin to his own two.
- The third knight is the strongest, but he can’t kill more than k=2k=2 other knights. It is optimal to kill the second and the fourth knights: 2+11+33=462+11+33=46.
- The fourth knight should kill the first and the second knights: 33+1+2=3633+1+2=36.
In the second example the first knight can’t kill anyone, while all the others should kill the one with the index less by one than their own.
In the third example there is only one knight, so he can’t kill anyone.
其实这个题也比较明了,基本上样例解释就告诉我们了做法
就是贪心做法,一个骑士能杀的其他骑士只能是其他的骑士,所以我们就先让所有的骑士来按武力值来排个序,就能保证上面的条件。那么我们只需要保证啥前面的k个金币数最大的就能达到再加上自己有的硬币就是答案了
题目最后要求我们要按原有顺序输出,那么最后记得按照顺序输出就行(好像在说废话
首先是我自己的实现代码:
#include <iostream>
#include <cstdio>
#include <cmath>
#include <ctype.h>
#include <algorithm>
#include <cstring>
#include <map>
#include <set>
#include <sstream>
#include <queue>
#define ll long long
#define re return
using namespace std;
struct nope
{
ll p;
ll c;
ll id;
ll ans;
}a[100000 + 10];
ll n, k;
// priority_queue<int> q; //下一份代码留有大用
bool cmp1(nope a, nope b){ //按力量从小到大
return a.p < b.p;
}
bool cmp2(nope a, nope b){ //编号从小到大
return a.id < b.id;
}
int main(){
cin >> n >> k;
for (ll i = 1; i <= n; i++){
cin >> a[i].p;
a[i].id = i;
}
for (ll i = 1; i <= n; i++){
cin >> a[i].c;
}
if(k == 0){ //特判一下,如果不特判,看完后面的代码就会发现解决不了k=0的情况
for (ll i = 1; i <= n; i++){
cout << a[i].c << " ";
}
return 0;
}
sort(a + 1, a + n + 1, cmp1);
ll max_sum = a[1].c; //前k个的最大和
ll min_c[200]; //存前k个中最小的那个,来更新答案
min_c[1] = a[1].c;
a[1].ans = a[1].c; //没得杀
for (ll i = 2; i <= k + 1; i++){ //前k个只能杀他前面的,所以不能只枚举到k,要到k + 1
a[i].ans = a[i - 1].ans + a[i].c; //其实就是一个前缀和
if(i != k + 1){
min_c[i] = a[i].c; //前k个的值
max_sum += a[i].c; //前k个的和
}
}
sort(min_c + 1, min_c + k + 1); //把我们存的目前最大的k个金币存好(用min做数组名的原因是想找这k个中最小的那个
for (ll i = k + 2; i <= n; i++){
if(min_c[1] < a[i - 1].c){ //有没有必要杀第i - 1个,i个是他自己不能杀;杀i-1的收益打还是不杀他的收益大
max_sum = max_sum - min_c[1] + a[i - 1].c; //需要把最小的那个剔除掉然后加上新的这个大硬币才难个更新max_sum
min_c[1] = a[i - 1].c;
sort(min_c + 1, min_c + 1 + k); //不用担心复杂度,k最大才10
}
a[i].ans = max_sum + a[i].c;
}
sort(a + 1, a + 1 + n, cmp2); //id排序输出
for (ll i = 1; i <= n; i++){
cout << a[i].ans << " ";
}
return 0;
}
然后我从题解学了一个方法。
当时也想着用单调队列来解决的,开始对于使用方法有点不熟就没用
#include <iostream>
#include <cstdio>
#include <cmath>
#include <ctype.h>
#include <algorithm>
#include <cstring>
#include <map>
#include <set>
#include <sstream>
#include <queue>
#include <vector>
#define ll long long
#define re return
using namespace std;
struct nope
{
ll p;
ll c;
ll id;
ll ans;
}a[100000 + 10];
ll n, k;
priority_queue<int> q;
vector<int> v; //不定数组可以不用在意长度直接往后加就行
bool cmp1(nope a, nope b){ //按力量从小到大
return a.p < b.p;
}
bool cmp2(nope a, nope b){ //编号从小到大
return a.id < b.id;
}
int main(){
cin >> n >> k;
for (ll i = 1; i <= n; i++){
cin >> a[i].p;
a[i].id = i;
}
for (ll i = 1; i <= n; i++){
cin >> a[i].c;
}
sort(a + 1, a + n + 1, cmp1);
a[1].ans = a[1].c;
q.push(a[1].c); //我们把第一个骑士,也就是最小的骑士的答案来准备好,好更新后面的答案
// v.push_back(a[1].c); //这里不能提前放进去,否则会造成1被多杀一次
for(int i = 2; i <= n; i++){
ll y = q.size();
ll t = min(k, y);
a[i].ans = a[i].c;
for (int j = 1; j <= t; j++){
int x = q.top();
q.pop();
v.push_back(x);
}
for (int j = 0; j < v.size(); j++)
{
a[i].ans += v[j];
q.push(v[j]);
}
v.clear();
q.push(a[i].c);//把这个人的钱放进去,因为下个人才能杀当前这个
}
sort(a + 1, a + 1 + n, cmp2);
for (ll i = 1; i <= n; i++){
cout << a[i].ans << " ";
}
return 0;
}