题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4020
题意描述:有n个顾客,m个广告,每个顾客可以有多个广告,每个广告有一个点击量和长度,现在要求每个顾客前k个访问量的长度总和的总和
分析:先按访问量从大到小排序,用一个数组记录所有顾客第k访问量的长度总和,那么我们要求每个顾客的前k个访问量的广告的长度的总和就等于所有顾客的第1、2。。。。k大的访问量的和的总和!!(有点阐述不清,详情见代码)
代码:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int M=500010;
const int N=100010;
struct node
{
int id,times,len;
}a[M];
int flag[M];
int num[N];//每个广告出现的次数
__int64 ans[M];//各个广告的前i个广告之和的之和
__int64 res[M];
bool cmp (int i, int j)
{
return a[i].times>a[j].times;
}
int main ()
{
int t,n,m,q,i,x;
int k=1;
scanf("%d",&t);
while(t--)
{
scanf("%d%d%d",&n,&m,&q);
for(i=1;i<=m;i++)
scanf("%d%d%d",&a[i].id,&a[i].times,&a[i].len);
for(i=1;i<=m;i++)
flag[i]=i;
sort(flag+1,flag+1+m,cmp);
for(i=1;i<=n;i++)
num[i]=0;
for(i=0;i<=m;i++)
ans[i]=0;
for(i=1;i<=m;i++)
{
num[a[flag[i]].id]++;
ans[num[a[flag[i]].id]]+=a[flag[i]].len;
}
res[0]=0;
for(i=1;i<=m;i++)
res[i]=res[i-1]+ans[i];
printf("Case #%d:\n",k++);
for(i=0;i<q;i++)
{
scanf("%d",&x);
if(x>m)//如果访问超出了最大的广告个数
printf("%I64d\n",res[m]);
else
printf("%I64d\n",res[x]);
}
}
return 0;
}