題意:N個customer,M個advertisement,每個ad只屬於一個cus,每個ad都有一個點擊量和一個長度值。現在對於每個詢問,求出所有cus的前k大點擊量的廣告的總長度。
對於每個ad,求出他在所屬的cus裏面的排名,這個一邊排序就可以了。
將長度累加到對應排名上面。樹狀數組維護查詢就可以了。
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
#define N 500010
ll s[N];
int n, m, q;
struct node {
int u, c, l;
bool operator<(const node&x ) const {
return (u<x.u) || (u==x.u && c>x.c);
}
} a[N];
inline int lowbit(int x) { return x & (-x); }
void add(int x, ll y) {
while (x <= m) {
s[x] += y;
x += lowbit(x);
}
}
ll sum(int x) {
ll ret = 0;
while (x) {
ret += s[x];
x -= lowbit(x);
}
return ret;
}
int main() {
#ifndef ONLINE_JUDGE
freopen("in.txt", "r", stdin);
#endif
int T;
scanf("%d", &T);
for (int cas=1; cas<=T; cas++) {
scanf("%d%d%d", &n, &m, &q);
for (int i=0; i<m; i++)
scanf("%d%d%d", &a[i].u, &a[i].c, &a[i].l);
sort(a, a+m);
memset(s, 0, sizeof(s));
int last = 0;
for (int i=0; i<m; i++) {
if (a[i].u != a[last].u) last = i;
add(i-last+1, (ll)a[i].l);
}
printf("Case #%d:\n", cas);
int k;
while (q--) {
scanf("%d", &k);
if (k > m) k = m;
printf("%I64d\n", sum(k));
}
}
return 0;
}