区间的查询,点修改,插入和删除。先姑且当作模板吧,略挫,慢慢补充,慢慢优化。
#include <algorithm> #include <iostream> #include <cstring> #include <cstdlib> #include <cstdio> #include <queue> #include <cmath> #include <stack> #include <map> #pragma comment(linker, "/STACK:1024000000"); #define EPS (1e-8) #define LL long long #define ULL unsigned long long #define _LL __int64 #define _INF 0x3f3f3f3f #define Mod 9999991 using namespace std; const int MAXN = 700100; struct N { //info int son[2],pre; //data int sta,ls,rs,s; int w,g[2]; bool mark[2]; }st[MAXN]; struct W { int sta,w; }num[200100]; void Output(int root) { if(root == -1) return ; Output(st[root].son[0]); printf("root = %d pre = %d data = %2d lg = %2d rg = %2d sta = %2d ls = %d rs = %d s = %d\n",root,st[root].pre,st[root].w,st[root].g[0],st[root].g[1],st[root].sta,st[root].ls,st[root].rs,st[root].s); Output(st[root].son[1]); } int Top; int Gcd(int a,int b) { int t; while(b) { t = a; a = b; b = t%b; } return a; } //更新st[root]的数据域 void Updata(int root) { st[root].ls = 0,st[root].rs = 0; st[root].g[st[root].sta] = st[root].w; st[root].g[1^st[root].sta] = 1; st[root].mark[st[root].sta] = true; st[root].mark[1^st[root].sta] = false; if(st[root].son[0] != -1) { if(st[root].mark[0] == true) st[root].g[0] = (st[st[root].son[0]].mark[0] ? Gcd(st[root].g[0],st[st[root].son[0]].g[0]) : st[root].g[0]); else st[root].g[0] = st[st[root].son[0]].g[0]; if(st[root].mark[1] == true) st[root].g[1] = (st[st[root].son[0]].mark[1] ? Gcd(st[root].g[1],st[st[root].son[0]].g[1]) : st[root].g[1]); else st[root].g[1] = st[st[root].son[0]].g[1]; st[root].mark[0] = (st[root].mark[0] || st[st[root].son[0]].mark[0]); st[root].mark[1] = (st[root].mark[1] || st[st[root].son[0]].mark[1]); st[root].ls = st[st[root].son[0]].s; } if(st[root].son[1] != -1) { if(st[root].mark[0] == true) st[root].g[0] = (st[st[root].son[1]].mark[0] ? Gcd(st[root].g[0],st[st[root].son[1]].g[0]) : st[root].g[0]); else st[root].g[0] = st[st[root].son[1]].g[0]; if(st[root].mark[1] == true) st[root].g[1] = (st[st[root].son[1]].mark[1] ? Gcd(st[root].g[1],st[st[root].son[1]].g[1]) : st[root].g[1]); else st[root].g[1] = st[st[root].son[1]].g[1]; st[root].mark[0] = (st[root].mark[0] || st[st[root].son[1]].mark[0]); st[root].mark[1] = (st[root].mark[1] || st[st[root].son[1]].mark[1]); st[root].rs = st[st[root].son[1]].s; } st[root].s = st[root].ls + st[root].rs + 1; } void Init(int &root,int s,int e,int pre) { if(s > e) return ; int mid = (s+e)>>1; root = Top++; st[root].w = num[mid].w; st[root].sta = num[mid].sta; st[root].pre = pre; st[root].son[0] = st[root].son[1] = -1; Init(st[root].son[0],s,mid-1,root); Init(st[root].son[1],mid+1,e,root); Updata(root); } //dir == 0,root为pre的左儿子,dir == 1时为右儿子。 void Rotate(int root,int dir) { //旋转操作 st[st[root].pre].son[dir] = st[root].son[1^dir]; st[root].son[1^dir] = st[root].pre; if(st[st[st[root].pre].pre].son[0] == st[root].pre) st[st[st[root].pre].pre].son[0] = root; else st[st[st[root].pre].pre].son[1] = root; int temp = st[root].pre; st[root].pre = st[st[root].pre].pre; st[temp].pre = root; if(st[temp].son[dir] != -1) st[st[temp].son[dir]].pre = temp; //更新数据域 Updata(temp); Updata(root); } //将root旋转到goal下面,goal == 0时即表示将root旋转至根节点位置。 int Splay(int root,int goal) { while(st[root].pre != goal) { Rotate(root,(st[st[root].pre].son[0] == root ? 0 : 1)); } return root; } int Search_Site(int root,int site) { while(st[root].ls + 1 != site) { if(st[root].ls + 1 < site) { site = site - st[root].ls - 1; root = st[root].son[1]; } else { root = st[root].son[0]; } } return root; } void Increase(int root,int site,int w,int sta,int &R) { root = Search_Site(root,site); R = Splay(root,0); //在根节点的右子树的最左边插入一个点 int tr = st[R].son[1]; st[R].son[1] = -1; int New = Top++; st[New].w = w; st[New].sta = sta; st[New].pre = 0; st[0].son[0] = New; st[R].pre = New; st[New].son[0] = R; st[tr].pre = New; st[New].son[1] = tr; Updata(R); Updata(New); R = New; } void Link(int &root,int tr,int pre) { if(root == -1) { root = tr; st[root].pre = pre; } else { Link(st[root].son[1],tr,root); } Updata(root); } //不存在删除所有节点的情况 void Decrease(int root,int site,int &R) { root = Search_Site(root,site); //Output(R); // printf("D site = %d root = %d R = %d\n",site,root,R); R = Splay(root,0); //删除根节点 R = st[root].son[0]; st[R].pre = st[root].pre; st[0].son[0] = R; int tr = st[root].son[1]; //将tr接到R的最右边。 Link(R,tr,root); Updata(R); } void Reinit(int root,int site,int &R) { root = Search_Site(root,site); R = Splay(root,0); st[R].sta ^= 1; Updata(R); } void Modify(int root,int site,int w,int &R) { root = Search_Site(root,site); R = Splay(root,0); st[R].w = w; Updata(R); } int Query(int root,int l,int r,int sta,int &R) { int lsite = Search_Site(root,l); int rsite = Search_Site(root,r); R = Splay(rsite,0); R = Splay(lsite,0); if(st[st[R].son[1]].son[0] == -1 || st[st[st[R].son[1]].son[0]].mark[sta] == false) return -1; return st[st[st[R].son[1]].son[0]].g[sta]; } int main() { //freopen("data.txt","r",stdin); //freopen("dataout.txt","w",stdout); int n,m; int i; int root; while(scanf("%d %d",&n,&m) != EOF) { for(i = 2;i <= n+1; ++i) { scanf("%d %d",&num[i].w,&num[i].sta); } // cout<<n<<" "<<m<<endl; num[1].w = 1,num[1].sta = 0; num[n+2].w = 1,num[n+2].sta = 0; //Top从1开始是为了将st[0]拿出来做 //根节点的虚拟父节点,在缩短代码的同时防止RE。 Top = 1,root = -1; Init(root,1,n+2,0); // cout<<"dfadsf"<<endl; st[0].son[0] = root,st[0].son[1] = -1; char order[2]; int site,sta,l,r,w; for(i = 1;i <= m; ++i) { scanf("%s",order); if(order[0] == 'I') { scanf("%d %d %d",&site,&w,&sta); // printf("i = %d site = %d\n",i+200000+1,site); Increase(root,site+1,w,sta,root); } else if(order[0] == 'D') { scanf("%d",&site); // printf("i = %d site = %d\n",i+200000+1,site); Decrease(root,site+1,root); } else if(order[0] == 'R') { scanf("%d",&site); Reinit(root,site+1,root); } else if(order[0] == 'M') { scanf("%d %d",&site,&w); Modify(root,site+1,w,root); } else if(order[0] == 'Q') { scanf("%d %d %d",&l,&r,&sta); printf("%d\n",Query(root,l,r+2,sta,root)); } //cout<<"ans = "<<st[root].s<<endl; } } return 0; }
ZOJ 3765 Lights Splay Tree的几种基本操作,布布扣,bubuko.com
ZOJ 3765 Lights Splay Tree的几种基本操作
原文地址:http://blog.csdn.net/zmx354/article/details/27229937