zoukankan      html  css  js  c++  java
  • 列队「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('
    ');
    				
    				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('
    ');
         	    	root[n+1]=merge(x,merge(y,z));
    			}
    		}
    	}
    	
    	#undef int
    }
    
    int main(){
    //	freopen(".in","r",stdin);
    //	freopen(".out","w",stdout);
    	Project::MAIN();
    }
    
    
  • 相关阅读:
    软件工程个人作业02
    第三周学习进度条
    《构建之法》阅读笔记01
    第二周学习进度条
    软件工程个人作业01
    大道至简第三章读后感
    动手动脑课后实践
    JAVA数字想加并输出
    大道至简第二章读后感
    大道至简读后感
  • 原文地址:https://www.cnblogs.com/ilverene/p/11828586.html
Copyright © 2011-2022 走看看