Codeforces Round #503 (by SIS, Div. 2) C. Elections
气死我了人生中第一次打cf就掉分了
A题大水题浪费太多时间囧明明都是A两题亮老师还上分了。。
表示C题打的时候就想到正解啊(而且还更加优秀,因为家里老爷机暴力跑的超龟以为不行 其实是没认真算复杂度),虽然不会证三分性,但是最后还是AC了,暴力1000ms+ 三分40ms+
看着就很奇淫的题,猛然脑海里就想到二分政党的最后得到的选票,然后发现没有单调性,但好像满足三分
然后每次就贪心,for一遍把那些比1政党本来就有的选票+要多拿的选票还要多的拿到比这个值少1
假如还不够要多拿的,那就在剩下的拿最小的凑够
#include<cstdio> #include<iostream> #include<cstring> #include<cstdlib> #include<algorithm> #include<cmath> #include<queue> using namespace std; typedef long long LL; int m; LL d[3100][3100],s[3100][3100]; struct node { LL d;int i,j; node(){} node(LL D,int I,int J){d=D,i=I,j=J;} friend bool operator >(node n1,node n2){return n1.d>n2.d;} friend bool operator <(node n1,node n2){return n1.d<n2.d;} }; priority_queue<node,vector<node>,greater<node> >q; LL check(int mid) { while(!q.empty())q.pop(); LL ret=0;int cc=0; mid+=d[1][0];if(mid==0)return (1LL<<62); for(int i=2;i<=m;i++) { if(d[i][0]>=mid) { int u=d[i][0]-mid+1; ret+=s[i][u]; if(u+1<=d[i][0])q.push(node(d[i][u+1],i,u+1)); cc+=u; } else if(d[i][0]>0)q.push(node(d[i][1],i,1)); } if(cc+d[1][0]<mid) { int p=mid-(cc+d[1][0]); while(p--) { node t=q.top();q.pop(); ret+=t.d; if(t.j+1<=d[t.i][0])q.push(node(d[t.i][t.j+1],t.i,t.j+1)); } } return ret; } int main() { // freopen("1.in","r",stdin); // freopen("1.out","w",stdout); int n,x;LL k; scanf("%d%d",&n,&m); for(int i=1;i<=m;i++)d[i][0]=0; for(int i=1;i<=n;i++) { scanf("%d%I64d",&x,&k); d[x][++d[x][0]]=k; } for(int i=2;i<=m;i++) { sort(d[i]+1,d[i]+d[i][0]+1); s[i][0]=0; for(int j=1;j<=d[i][0];j++) s[i][j]=s[i][j-1]+d[i][j]; } int l=0,r=n-d[1][0]; while(r-l>3) { int mid=(l+r)/2; int mmid=(mid+r)/2; LL sum1=check(mid),sum2=check(mmid); if(sum1>sum2)l=mid+1; else r=mmid-1; } LL ans=check(l); for(int i=l+1;i<=r;i++) { LL dd=check(i); if(dd<ans)ans=dd; } printf("%I64d\n",ans); return 0; }
pain and happy in the cruel world.