LUOGU P3960 列队 (noip2017 day2T3)
解题思路
记得当时考试我还是个孩子,啥也不会QAQ。现在回头写,用动态开点的线段树,在每行和最后一列开线段树,然后对于每次询问,把x行y列的删去,然后再把x行m列的元素加入x行这个线段树,然后再把删去元素加到最后一列里,用一个vector维护变化后的标号。
代码
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<cstdlib> #include<vector> using namespace std; const int MAXN = 1000005; typedef long long LL; inline int rd(){ int x=0,f=1;char ch=getchar(); while(!isdigit(ch)) {f=ch=='-'?0:1;ch=getchar();} while(isdigit(ch)) {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();} return f?x:-x; } vector<LL> g[MAXN]; int n,m,q,Max,num,rt[MAXN]; LL pos; int sum[MAXN<<2],ls[MAXN<<2],rs[MAXN<<2]; LL query(int x,int l,int r,int k){ if(l==r) return l; int mid=l+r>>1,sizl=mid-l+1-sum[ls[x]]; if(sizl>=k) return query(ls[x],l,mid,k); else return query(rs[x],mid+1,r,k-sizl); } void modify(int &x,int l,int r){ if(!x){ x=++num; ls[x]=rs[x]=0; } sum[x]++; if(l<r){ int mid=l+r>>1; if(mid>=pos) modify(ls[x],l,mid); else modify(rs[x],mid+1,r); } } LL Del_r(int x,LL now){ pos=query(rt[n+1],1,Max,x); modify(rt[n+1],1,Max); LL ret=pos<=n?1ll*pos*m:g[n+1][pos-n-1]; g[n+1].push_back(now?now:ret); return ret; } LL Del_l(int x,int y){ pos=query(rt[x],1,Max,y);modify(rt[x],1,Max); LL ret=pos<m?1ll*(x-1)*m+pos:g[x][pos-m]; g[x].push_back(Del_r(x,ret)); return ret; } int main(){ n=rd(),m=rd(),q=rd();Max=max(n,m)+q; int x,y; while(q--){ x=rd(),y=rd(); if(y==m) printf("%lld\n",Del_r(x,0)); else printf("%lld\n",Del_l(x,y)); } return 0; }