题目链接:http://codeforces.com/problemset/problem/421/D
题目大意:每个人说出自己认为的背锅的两个人,最后大BOSS找两个人来背锅,要求至少符合p个人的想法。最终选出的两个人中只有有一个在自己的预测内就算符合想法。
解题思路:统计每个人背锅的次数,排个序。找出相加大于等于p的对数。
然后去重:需要去重的原因,假如有且只有两个人的预测都是 1和2 (其他人的预测不涉及1,、2),则1、2这对组合在我们的计算中符合度为4,实际符合度为2,因此需 要去重
去重过程 x和y分别表示每个人的预测,(x<y),同样的一组预测x和y出现了c次,假如cnt[x]+cnt[y]>=y&&cnt[x]+cnt[y]-c<p,则ans--。
代码如下:
1 #include <cmath> 2 #include <cstdio> 3 #include <cstring> 4 #include <iostream> 5 #include <algorithm> 6 using namespace std; 7 #define FFF 300005 8 int cnt[FFF],to[FFF]; 9 struct node 10 { 11 int x,y; 12 }f[FFF]; 13 bool cmp(node a,node b){ 14 if(a.x==b.x) 15 return a.y<b.y; 16 else 17 return a.x<b.x; 18 } 19 int main() 20 { 21 int n,p; 22 scanf("%d%d",&n,&p); 23 memset(cnt,0,sizeof(cnt)); 24 for(int i=0;i<n;i++) 25 { 26 scanf("%d%d",&f[i].x,&f[i].y); 27 if(f[i].x>f[i].y) 28 { 29 int t=f[i].x; 30 f[i].x=f[i].y; 31 f[i].y=t; 32 } 33 cnt[f[i].x]++; 34 cnt[f[i].y]++; 35 } 36 for(int i=1;i<=n;i++)to[i]=cnt[i]; 37 long long ans=0,now=n; 38 sort(cnt+1,cnt+n+1); 39 for(int i=1;i<=n;i++) { 40 if(cnt[i]>=p) 41 ans+=n-1; 42 else{ 43 while(cnt[now]>=p-cnt[i]) 44 now--; 45 if(cnt[now+1]+cnt[i]>=p){ 46 if(cnt[now+1]>cnt[i]) 47 ans+=n-now; 48 else 49 ans+=n-now-1; 50 } 51 } 52 // cout<<"now="<<now<<" cnt[now]="<<cnt[now]<<" ans="<<ans<<endl; 53 } 54 ans/=2; 55 sort(f,f+n,cmp); 56 node tmp; 57 tmp.x=tmp.y=0; 58 memset(cnt,0,sizeof(cnt)); 59 int c=0; 60 for(int i=0;i<n;i++) 61 { 62 if(tmp.x==f[i].x&&tmp.y==f[i].y) 63 c++; 64 else 65 { 66 if(tmp.x&&to[tmp.x]+to[tmp.y]>=p&&to[tmp.x]&&to[tmp.x]+to[tmp.y]-c<p) 67 ans--; 68 tmp.x=f[i].x; 69 tmp.y=f[i].y; 70 c=1; 71 } 72 // cout<<"tmp.x="<<tmp.x<<" tmp.y="<<tmp.y<<" ans="<<ans<<endl; 73 } 74 if(to[tmp.x]+to[tmp.y]>=p&&to[tmp.x]&&to[tmp.x]+to[tmp.y]-c<p) 75 ans--; 76 cout<<ans<<endl; 77 return 0; 78 }