洛谷P3960 [NOIP2017] 列队

 

数据结构题还是挺好玩的

注意到每次只变动三个点:(x,y),(x,m),(n,m),其他地方都是整块移动。

可以开n+1个线段树,前n个存每行前m-1个人,最后一个存第m列的人。

(x,y)位置的人出列时,抽出该位置的标号,加到第n+1个线段树的最后面去,抽出第n+1个线段树的第x个元素(即(x,m),加到第x个线段树的最后面去。

↑实现这一操作,可以记线段树的size,每次二分查询树上第k个元素即可确定位置。

↑当然树不可能全建出来,需要动态开点。尚未申请的结点,size直接用$ r-l+1 $计算。

 

写到一半想到不需要专门抽出来,只需要记录该行到该位置为止抽出过a个数,找(x,y)时实际找(x,y+a)即可。可以开个vector什么的存新加到队伍最右边的人。

这样的话更加方便&优美,而且可以用树状数组写,代码量也减小了。

但是看着自己写了一大半的代码不舍得丢,还是强行按原计划敲完了。

 

————

老年退役选手连NOIP题都做不来了。做这题成功遇到了数组开小,变量写混,初始化错误,输出错误等等问题,调了好久。

不开心QAQ

————

  1 #include<iostream>
  2 #include<cstdio>
  3 #define LL long long
  4 using namespace std;
  5 const int mxn=800010;
  6 struct node{
  7     int sz,lc,rc;
  8     LL mk;
  9 }t[mxn<<3];
 10 int cnt=0,mod=0;
 11 int root[mxn];
 12 int n,N,m,Q;
 13 inline int getsz(int l,int r,int rt){
 14     if(rt)return t[rt].sz;
 15     return r-l+1;
 16 }
 17 void pushup(int l,int r,int rt){
 18     int tmp=0;
 19     int mid=(l+r)>>1;
 20     tmp+=getsz(l,mid,t[rt].lc);
 21     tmp+=getsz(mid+1,r,t[rt].rc);
 22     t[rt].sz=tmp;
 23     return;
 24 }
 25 int anspos;
 26 int query(int k,int l,int r,int &rt){
 27     if(!rt){
 28         rt=++cnt;
 29         t[rt].sz=r-l+1;
 30     }
 31     if(l==r){
 32         if(!t[rt].mk){//计算标号 
 33             if(mod==n+1)t[rt].mk=(LL)l*m;
 34             else t[rt].mk=(LL)(mod-1)*m+l;
 35         }
 36         anspos=l;
 37         return rt;
 38     }
 39     int mid=(l+r)>>1,tmp=getsz(l,mid,t[rt].lc);
 40     if(k<=tmp)
 41         return query(k,l,mid,t[rt].lc);
 42     else return query(k-tmp,mid+1,r,t[rt].rc);
 43 }
 44 void update(LL v,int p,int l,int r,int &rt){
 45     if(!rt){
 46         rt=++cnt;
 47         t[rt].sz=r-l+1;
 48     }
 49     if(l==r){
 50         t[rt].mk=v;
 51         if(!v){//del
 52             t[rt].sz=0;
 53         }
 54         else t[rt].sz=1;
 55         return;
 56     }
 57     int mid=(l+r)>>1;
 58     if(p<=mid)update(v,p,l,mid,t[rt].lc);
 59     else update(v,p,mid+1,r,t[rt].rc);
 60     pushup(l,r,rt);
 61     return;
 62 }
 63 void info(int l,int r,int rt){
 64     printf("  %d %d rt:%d sz:%d\n",l,r,rt,getsz(l,r,rt));
 65     if(!rt)return;
 66     if(l==r)return;
 67     int mid=(l+r)>>1;
 68     info(l,mid,t[rt].lc);
 69     info(mid+1,r,t[rt].rc);
 70     return;
 71 }
 72 int main(){
 73 //    freopen("2017phalanx.in","r",stdin);
 74 //    freopen("2017phalanx.out","w",stdout);
 75     int i,j,x,y,tmp;
 76     LL tmp2;
 77     scanf("%d%d%d",&n,&m,&Q);
 78     N=max(max(n,m),Q)<<1;
 79     while(Q--){
 80         scanf("%d%d",&x,&y);
 81         if(y==m){
 82             mod=n+1;
 83             tmp=query(x,1,N,root[n+1]);
 84             tmp2=t[tmp].mk;
 85             printf("%lld\n",t[tmp].mk);
 86             update(0,anspos,1,N,root[n+1]);
 87             tmp=query(n,1,N,root[n+1]);
 88             update(tmp2,anspos,1,N,root[n+1]);
 89         }
 90         else{
 91 //            printf("  in\n");
 92             mod=x;
 93             tmp=query(y,1,N,root[x]);
 94             tmp2=t[tmp].mk;
 95             printf("%lld\n",t[tmp].mk);
 96             update(0,anspos,1,N,root[x]);//出队 
 97 //            printf("anspos:%d\n",anspos);
 98             //
 99             mod=n+1;
100             tmp=query(n+1,1,N,root[n+1]);
101             update(tmp2,anspos,1,N,root[n+1]);
102 //            printf("UPD: mk:%d pos:%d\n",tmp2,anspos);
103             //
104             tmp=query(x,1,N,root[n+1]);
105             tmp2=t[tmp].mk;
106 //            printf("bu:%d anspos:%d\n",tmp2,anspos);
107             update(0,anspos,1,N,root[n+1]);
108             mod=x;
109             tmp=query(m-1,1,N,root[x]);
110             update(tmp2,anspos,1,N,root[x]);
111             //
112         }
113 //        info(1,N,root[n+1]);
114     }
115     return 0;
116 }

 

posted @ 2018-06-21 21:43  SilverNebula  阅读(479)  评论(0编辑  收藏  举报
AmazingCounters.com