poj2454 Jersey Politics

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;
}

 

posted @ 2018-10-16 21:36  kafuuchino  阅读(119)  评论(0编辑  收藏  举报