Poj 2886 Who Gets the Most Candies?

来源:互联网 发布:手机美化主题软件 编辑:程序博客网 时间:2024/06/03 17:36

一个简单的线段树上二分+反素数

线段树上二分其实就是单点更新单点查询

具体的每一个节点保存他的所表示的区间内剩余的未出对的人数

然后给出一个人在队伍中的位置的话可以类似于splay往下找点的姿势去找到位置所对应的绝对位置(其实也就是这个节点在原区间所对应的位置


还有需要注意的是在删除一个点之后往前走和往后走是需要分开处理的,考虑这个点后面的点的位置都往后挪了一位


然后反素数只是打表而已,感觉没什么


#include<cstdio>#include<algorithm>#include<cstring>#include<iostream>using namespace std;#define root 1,1,n#define lson o<<1,l,m#define rson o<<1|1,m+1,r#define Mid int m = l + (r - l) /2#define Now int o,int l,int rconst int maxn = 562345;int arr[maxn*4];void update(Now,int pos,int val){if(l == r){arr[o] = val;return;}Mid;if(pos <= m){update(lson,pos,val);}else{update(rson,pos,val);}arr[o] = arr[o<<1] + arr[o<<1|1];}int query(Now,int id){if(l==r){return l;}Mid;if(arr[o<<1] >= id){return query(lson,id);}else{return query(rson,id-arr[o<<1]);}}char name[maxn][30];int order[maxn];int offset[maxn];int hug[40]={1,2,4,6,12,24,36,48,60,120,180,240,360,720,840,1260,1680,2520,5040,7560,10080,15120,    20160,25200,27720,45360,50400,55440,83160,110880,166320,221760,277200,332640,498960,    554400};int frac[40]={1,2,3,4,6,8,9,10,12,16,18,20,24,30,32,36,40,48,60,64,72,80,84,90,96,100,108,120,128,    144,160,168,180,192,200,216};int poser[maxn];int cal(int x){    return frac[lower_bound(hug,hug+36,x)-hug];}int main(){int n,k;memset(poser,0,sizeof(poser));for(int i=0;i<36;i++){        poser[hug[i]]=hug[i];}for(int i=1;i<500100;i++){        if(!poser[i])            poser[i] = poser[i-1];}while(~scanf("%d %d",&n,&k)){for(int i=1;i<=n;i++){scanf("%s",name[i]);scanf("%d",&offset[i]);}for(int i=1;i<=n;i++){update(root,i,1);}int left = n;int lenth=0;k--;while(left>0){int id = query(root,k+1);update(root,id,0);order[lenth++]=id;left--;if(offset[id]>0)             <span style="white-space:pre"></span>k--;if(left)                k = ((k+offset[id])%left+left) % left;}        int ans = order[poser[n]-1];        printf("%s",name[ans]);        printf(" %d\n",cal(poser[n]));}return 0;}


0 0
原创粉丝点击