3223:Tyvj 1729文芸バランスツリー

4224 ワード

3223:Tyvj 1729文芸バランスツリー
Time Limit: 10 Sec  
メモリLimit: 128 MB
Submit: 2466  
Solved: 1380
[Submit][Sttus][Dispacs]
Description
データ構造(件名参照可能)を書いて、順序正しい数列を維持する必要があります.ここでは、次のような動作を提供します. 4 3 2 1,反転区間が[2,4]だったら、結果は5です. 2 3 4 1 
Input
第一行為n,m nは初期シーケンスにn個の数があることを示し、このシーケンスは順次(1,2…n−1,n)である.  mは反転操作回数を表します.次に、m行の各行数[l,r] データ保証 1<=l<=r==n 
Output
 
一行n個の数字を出力して、元のシーケンスがm回変換された後の結果を表します. 
Sample Input
5 3 1 3 1 3 1 3 1 4
Sample Output
4 3 2 1 5
HINT
N、M<=100000
ソurce
バランスツリー
[Submit][Sttus][Dispacs]
splayは区間問題を解決します.
操作のたびにl-1をルートr+1に変えて、ルートの右の息子に変えます.このようにr+1の左の息子は[l,r]です.そしてマークします.
マークはxorで操作する必要があります.反転が可逆的ですから.
そして挿入するたびに、新しく挿入された点をルートに移動します.
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<vector>
#include<queue>
using namespace std;

const int maxn = 1E5 + 10;

int n,m,ans[maxn];

class data{
	private:
		struct Node{
			Node *ch[2];
			int num,mark,siz;
		}*root,*tot,pool[maxn];
		
		void maintain(Node *&x) {
			int s0 = (x->ch[0] == NULL)?0:x->ch[0]->siz;
			int s1 = (x->ch[1] == NULL)?0:x->ch[1]->siz;
			x->siz = s0+s1+1;
		}
		
		void rotate(Node *&x,int d) {
			Node *y = x->ch[d]; //y->fa = x->fa; 
			x->ch[d] = y->ch[d^1]; //y->ch[d^1]->fa = x;
			y->ch[d^1] = x; //x->fa = y;
			maintain(x); 
			x = y; 
			maintain(x);
		}
		
		int Insert(Node *&x,int num) {
			int ret = 0;
			if (x == NULL) {
				x = ++tot;
				x->ch[0] = x->ch[1] = NULL;
				x->num = num; x->siz = 1;
				x->mark = 0; return 1;
			}
			
			int d = (x->num > num)?0:1;
			int s0 = (x->ch[0] == NULL)?0:x->ch[0]->siz;
			ret = s0+1;
			int sum = Insert(x->ch[d],num);
			//x->ch[d]->fa = x;
			maintain(x);
			return ret + sum;
		}
		
		void pushdown(Node *&x) {
			if (x->mark) {
				swap(x->ch[0],x->ch[1]);
				if (x->ch[0] != NULL) x->ch[0]->mark ^= 1;
				if (x->ch[1] != NULL) x->ch[1]->mark ^= 1;
				x->mark = 0;
			}
		}
		
		/*Node* find(Node *x,int rank) {
			pushdown(x);
			int s0 = (x->ch[0] == NULL)?0:x->ch[0]->siz;
			if (s0+1 == rank) return x;
			else if (s0+1 > rank) return find(x->ch[0],rank);
			else return find(x->ch[1],rank-s0-1);
		}*/
		
		void splay(Node *&x,int rank) {
			pushdown(x);
			int s0 = (x->ch[0] == NULL)?0:x->ch[0]->siz;
			if (s0+1 != rank) {
				int d;
				if (s0+1 >= rank) d = 0;
				else d = 1,rank = rank - s0 - 1;
				pushdown(x->ch[d]);
				int s1 = (x->ch[d]->ch[0] == NULL)?0:x->ch[d]->ch[0]->siz;
				if (s1+1 != rank) {
					int d2;
					if (s1+1 >= rank) d2 = 0;
					else d2 = 1,rank = rank - s1 - 1;
					splay(x->ch[d]->ch[d2],rank);
					if (d == d2) rotate(x,d);
					else rotate(x->ch[d],d2);
				}
				rotate(x,d); 
			}
		}
		
		void DFS(Node *x,int sum) {
			pushdown(x);
			int s0 = (x->ch[0] == NULL)?0:x->ch[0]->siz;
			ans[s0+1+sum] = x->num;
			if (x->ch[0] != NULL) DFS(x->ch[0],sum);
			if (x->ch[1] != NULL) DFS(x->ch[1],sum+s0+1);
		}
		
	public:
		data() {
			root = NULL;
			tot = pool;
		}
		
		int Ins(int num) {
			return Insert(root,num);
		}
		
		void setmark() {
			//pushdown(root);
			//pushdown(root->ch[1]);
			root->ch[1]->ch[0]->mark ^= 1;
		}

		void spl(int rank,int typ) {
			if (!typ) splay(root,rank);
			else {
				pushdown(root);
				int s0 = (root->ch[0] == NULL)?0:root->ch[0]->siz;
				splay(root->ch[1],rank-s0-1);
			}
		}
		
		void dfs() { 
			DFS(root,0);
		}
};

int main()
{
	#ifdef YZY
		   freopen("yzy.txt","r",stdin);
	#endif
	
	static data tree;
	cin >> n >> m;
	for (int i = 0; i <= n+1; i++) 
		tree.spl(tree.Ins(i),0);
	//tree.dfs();
	
	while (m--) {
		int l,r;
		scanf("%d%d",&l,&r);
		tree.spl(l,0); 
		tree.spl(r+2,1);
		tree.setmark();
		//tree.dfs();
	}
	
	tree.dfs();
	for (int i = 2; i <= n+1; i++) {
		printf("%d ",ans[i]);
	}
	
	return 0;
}