列队「NOIP2017」
题意
懒得粘贴了,自己去找吧。
思路
啊哈我重构了代码,换了fhq treap,这次秒过了。
思路还是比较显然的,就每行一棵treap,然后结尾一棵treap。
注意我们不可能维护每一个值,所以肯定是维护区间,那么把人叫走的操作就是将区间拆成三块,然后把中间那块拿走。在实现上就专门写了一个split_new
来实现拆区间。
代码
/*
By Nero Claudius Caeser Augustus Germanicus,
Emperor of the Roman Empire.
*/
#include <bits/stdc++.h>
using namespace std;
namespace StandardIO{
template<typename T>void read(T &x){
x=0;T f=1;char c=getchar();
for(; c<'0'||c>'9'; c=getchar()) if(c=='-') f=-1;
for(; c>='0'&&c<='9'; c=getchar()) x=x*10+c-'0';
x*=f;
}
template<typename T>void write(T x){
if(x<0) putchar('-'),x*=-1;
if(x>=10) write(x/10);
putchar(x%10+'0');
}
} using namespace StandardIO;
namespace Project{
#define int long long
const int N=300300;
int n,m,q;
int tot;
int root[N];
int l[N*20],r[N*20],ch[N*20][2],size[N*20],rnd[N*20];
inline int newNode(int _l,int _r){++tot,l[tot]=_l,r[tot]=_r,size[tot]=_r-_l+1,rnd[tot]=rand();return tot;}
inline void pushup(int pos){size[pos]=size[ch[pos][0]]+size[ch[pos][1]]+r[pos]-l[pos]+1;}
int merge(int x,int y){
if(!x||!y) return x+y;
if(rnd[x]<rnd[y]){
ch[x][1]=merge(ch[x][1],y);
pushup(x);
return x;
}else{
ch[y][0]=merge(x,ch[y][0]);
pushup(y);
return y;
}
}
void split_new(int now,int k){
if(k>=r[now]-l[now]+1) return;
int split_point=l[now]+k-1;
int right=newNode(split_point+1,r[now]);
r[now]=split_point;
ch[now][1]=merge(right,ch[now][1]);
pushup(now);
}
void split(int now,int k,int &x,int &y){
if(!now) x=y=0;
else{
if(size[ch[now][0]]>=k) y=now,split(ch[now][0],k,x,ch[now][0]);
else{
split_new(now,k-size[ch[now][0]]);
x=now,split(ch[now][1],k-size[ch[now][0]]-(r[now]-l[now]+1),ch[now][1],y);
}
pushup(now);
}
}
void MAIN(){
srand((unsigned)time(NULL));
read(n),read(m),read(q);
for(register int i=1; i<=n; ++i){
root[i]=newNode((i-1)*m+1,i*m-1);
}
for(register int i=1; i<=n; ++i){
root[n+1]=merge(root[n+1],newNode(i*m,i*m));
}
for(register int i=1,a,b; i<=q; ++i){
read(a),read(b);
if(b!=m){
int x,y,z;
split(root[a],b,x,y);
split(x,b-1,x,z);
write(l[z]),putchar('\n');
int x1,y1,z1;
split(root[n+1],a,x1,y1);
split(x1,a-1,x1,z1);
root[a]=merge(x,merge(y,z1));
root[n+1]=merge(x1,merge(y1,z));
}else{
int x,y,z;
split(root[n+1],a,x,y);
split(x,a-1,x,z);
write(l[z]),putchar('\n');
root[n+1]=merge(x,merge(y,z));
}
}
}
#undef int
}
int main(){
// freopen(".in","r",stdin);
// freopen(".out","w",stdout);
Project::MAIN();
}