poj2454 Jersey Politics
震惊!手写swap竟比stl快30ms!
poj不能用time(0) (大雾)
题意:给定一长度为$3k(1<=k<=60)$的序列,把它划分成等长的三段(元素可交换),要求至少两段的和大于$500*k$,求满足上述条件的一个划分(保证有解)。
先按权值从大到小排序,扔掉最后k个
蓝后对于前2k个,我们维护每段的和
每次随机交换一个元素,重新计算和是否符合条件
end.
#include<iostream> #include<ctime> #include<cstdio> #include<cstring> #include<cstdlib> #include<algorithm> #define re register using namespace std; struct data{ int v,id; bool operator < (const data &tmp) const{return v>tmp.v;} }a[200]; int k,n,s1,s2; int main(){ srand(19260817); scanf("%d",&k); s1=s2=0; n=k*3; for(re int i=1;i<=n;++i) scanf("%d",&a[i].v),a[i].id=i; sort(a+1,a+n+1); for(re int i=1;i<=k;++i) s1+=a[i].v,s2+=a[i+k].v; while(s1<=k*500||s2<=k*500){ int x=rand()%k+1,y=rand()%k+1+k; s1=s1-a[x].v+a[y].v; s2=s2-a[y].v+a[x].v; //swap(a[x],a[y]); int tmp=a[x].id; a[x].id=a[y].id; a[y].id=tmp; tmp=a[x].v; a[x].v=a[y].v; a[y].v=tmp; } for(re int i=1;i<=n;++i) printf("%d\n",a[i].id); return 0; }