洛谷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 }
本文为博主原创文章,转载请注明出处。