首页 > 技术文章 > 列队「NOIP2017」

ilverene 2019-11-09 23:54 原文

题意

懒得粘贴了,自己去找吧。


思路

啊哈我重构了代码,换了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();
}

推荐阅读