昨天讲了splay,然而一脸蒙蔽,今天写了个模版
洛谷p3369
没错,标准模版
您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:
第一行为nnn,表示操作的个数,下面nnn行每行有两个数optoptopt和xxx,optoptopt表示操作的序号( 1≤opt≤6 1 \leq opt \leq 6 1≤opt≤6 )
输出格式:对于操作3,4,5,63,4,5,63,4,5,6每行输出一个数,表示对应答案
10 1 106465 4 1 1 317721 1 460929 1 644985 1 84185 1 89851 6 81968 1 492737 5 493598
106465 84185 492737
时空限制:1000ms,128M
1.n的数据范围: n≤100000 n \leq 100000 n≤100000
2.每个数的数据范围: [−107,107][-{10}^7, {10}^7][−107,107]
来源:Tyvj1728 原名:普通平衡树
在此鸣谢
细节决定一切,模版要慢慢打
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int inf=1e7+10; 4 const int maxn=200005; 5 int par[maxn],cnt[maxn],ch[maxn][2],size[maxn],val[maxn],ncnt=0,n,root; 6 void pushup(int x){ 7 size[x]=size[ch[x][0]]+size[ch[x][1]]+cnt[x]; 8 } 9 bool chk(int x){ 10 return ch[par[x]][1]==x; 11 } 12 void rotate(int x){ 13 int y=par[x],z=par[y],k=chk(x),w=ch[x][k^1]; 14 ch[y][k]=w; 15 par[w]=y; 16 ch[z][chk(y)]=x; 17 par[x]=z; 18 ch[x][k^1]=y; 19 par[y]=x; 20 pushup(y);pushup(x); 21 } 22 void splay(int x,int goal=0){ 23 while(par[x]!=goal){ 24 int y=par[x],z=par[y]; 25 if(z!=goal){ 26 if(chk(x)==chk(y)) rotate(y); 27 else rotate(x); 28 } 29 rotate(x); 30 } 31 if(!goal) root=x; 32 } 33 void insert(int x){ 34 int cur=root,fa=0; 35 while(val[cur]!=x&&cur){ 36 fa=cur; 37 cur=ch[cur][x>val[cur]]; 38 } 39 if(cur){ 40 cnt[cur]++; 41 } 42 else { 43 cur=++ncnt;val[cur]=x; 44 if(fa) 45 ch[fa][x>val[fa]]=cur; 46 ch[cur][0]=ch[cur][1]=0; 47 size[cur]=1;cnt[cur]=1; 48 par[cur]=fa; 49 } 50 splay(cur); 51 } 52 void find(int x){ 53 int cur=root; 54 while(val[cur]!=x&&ch[cur][x>val[cur]]) cur=ch[cur][x>val[cur]]; 55 splay(cur); 56 } 57 int kth(int k){ 58 int cur=root; 59 while(1){ 60 if(size[ch[cur][0]]>=k) cur=ch[cur][0]; 61 else if(size[ch[cur][0]]+cnt[cur]>=k) return cur; 62 else { 63 k-=size[ch[cur][0]]+cnt[cur]; 64 cur=ch[cur][1]; 65 } 66 } 67 } 68 int pre(int x){ 69 find(x); 70 int cur=root; 71 if(val[cur]<x) return cur; 72 cur=ch[cur][0]; 73 while(ch[cur][1]) cur=ch[cur][1]; 74 return cur; 75 } 76 int suc(int x){ 77 find(x); 78 int cur=root; 79 if(val[cur]>x) return cur; 80 cur=ch[cur][1]; 81 while(ch[cur][0]) cur=ch[cur][0]; 82 return cur; 83 } 84 void remove(int x){ 85 int last=pre(x),next=suc(x); 86 splay(last); 87 splay(next,last); 88 if(cnt[ch[next][0]]==1){ 89 ch[next][0]=0; 90 } 91 else { 92 cnt[ch[next][0]]--; 93 splay(ch[next][0]); 94 } 95 } 96 int main(){ 97 scanf("%d",&n); 98 insert(inf);insert(-inf); 99 for(int i=1;i<=n;i++){ 100 int opt,x; 101 scanf("%d%d",&opt,&x); 102 switch(opt){ 103 case 1: 104 insert(x); 105 break; 106 case 2: 107 remove(x); 108 break; 109 case 3: 110 find(x); 111 printf("%d\n",size[ch[root][0]]); 112 break; 113 case 4: 114 printf("%d\n",val[kth(x+1)]); 115 break; 116 case 5: 117 printf("%d\n",val[pre(x)]); 118 break; 119 case 6: 120 printf("%d\n",val[suc(x)]); 121 break; 122 } 123 } 124 return 0; 125 }
还有一道要转化的题
洛谷p1503
小卡正在新家的客厅中看电视。电视里正在播放放了千八百次依旧重播的《亮剑》,剧中李云龙带领的独立团在一个县城遇到了一个鬼子小队,于是独立团与鬼子展开游击战。
描述 县城里有n个用地道相连的房子,第i个只与第i-1和第i+1个相连。这是有m个消息依次传来
1、消息为D x:鬼子将x号房子摧毁了,地道被堵上。
2、消息为R :村民们将鬼子上一个摧毁的房子修复了。
3、消息为Q x:有一名士兵被围堵在x号房子中。
李云龙收到信息很紧张,他想知道每一个被围堵的士兵能够到达的房子有几个。
第一行2个整数n,m(n,m<=50000)。
接下来m行,有如题目所说的三种信息共m条。
输出格式:对于每一个被围堵的士兵,输出该士兵能够到达的房子数。
若士兵被围堵在摧毁了的房子中,那只能等死了。。。。。。
当然这题暴力可过,但是splay也还行
不能把没有摧毁的房子插进去,而是把被摧毁的插进去,这样操作就简单了,因为还有修复,所以要开个栈来保存被摧毁的房子编号
计算房子数的话就先查看当前节点是否在树中,在的话直接输0,否则找前驱与后驱,注意相减后还要减一
初始化时插入0和n+1
还有可能会读入奇奇怪怪的字符,所以读字符时要处理下
1 #include<stack> 2 #include<cstdio> 3 using namespace std; 4 const int maxn = 5e4+5; 5 inline int read(){ 6 int x=0,f=1;char ch=getchar(); 7 while(ch>‘9‘||ch<‘0‘) {if(ch==‘-‘) f=-1;ch=getchar();} 8 while(ch>=‘0‘&&ch<=‘9‘) {x=x*10+ch-‘0‘;ch=getchar();} 9 return x*f; 10 } 11 void getc(char &c){//处理字符,第一次没这样做直接爆零(只能说数据坑 12 c=getchar(); 13 while(c!=‘D‘&&c!=‘R‘&&c!=‘Q‘){ 14 c=getchar(); 15 } 16 } 17 stack<int> s; 18 int ch[maxn][2],par[maxn],size[maxn],val[maxn],cnt[maxn],root,n,m,ncnt; 19 20 void pushup(int x){size[x]=size[ch[x][0]]+size[ch[x][1]]+cnt[x];} 21 22 int chk(int x){return x==ch[par[x]][1];} 23 24 void rotate(int x){ 25 int y=par[x],z=par[y],k=chk(x),w=ch[x][k^1]; 26 ch[y][k]=w; 27 par[w]=y; 28 ch[z][chk(y)]=x; 29 par[x]=z; 30 ch[x][k^1]=y; 31 par[y]=x; 32 pushup(y); 33 pushup(x); 34 } 35 36 void splay(int x,int goal=0){ 37 while(par[x]!=goal){ 38 int y=par[x],z=par[y]; 39 if(z!=goal){ 40 if(chk(y)==chk(x)) rotate(y); 41 else rotate(x); 42 } 43 rotate(x); 44 } 45 if(!goal) root=x; 46 } 47 48 void find(int x){ 49 int cur=root; 50 while(val[cur]!=x&&ch[cur][x>val[cur]]) cur=ch[cur][x>val[cur]]; 51 splay(cur); 52 } 53 54 int pre(int x){ 55 find(x); 56 if(val[root]<x) return root; 57 int cur=ch[root][0]; 58 while(ch[cur][1]) cur=ch[cur][1]; 59 return cur; 60 } 61 62 int suc(int x){ 63 find(x); 64 if(val[root]>x) return root; 65 int cur=ch[root][1]; 66 while(ch[cur][0]) cur=ch[cur][0]; 67 return cur; 68 } 69 70 void remove(int x){ 71 int last=pre(x),next=suc(x); 72 splay(last); 73 splay(next,last); 74 ch[next][0]=0; 75 } 76 77 void insert(int x){ 78 int cur=root,fa=0; 79 while(val[cur]!=x&&cur) fa=cur,cur=ch[cur][x>val[cur]]; 80 if(!cur){ 81 cur=++ncnt;val[cur]=x; 82 if(fa) 83 ch[fa][x>val[fa]]=cur; 84 ch[cur][0]=ch[cur][1]=0; 85 size[cur]=1;cnt[cur]=1; 86 par[cur]=fa; 87 } 88 else cnt[cur]++; 89 splay(cur); 90 } 91 92 int main(){ 93 n=read(),m=read(); 94 insert(0); 95 insert(n+1); 96 for(int i=1;i<=m;i++){ 97 char a;getc(a); 98 if(a==‘D‘){ 99 int x=read(); 100 insert(x); 101 s.push(x); 102 } 103 else if(a==‘R‘){ 104 remove(s.top()); 105 s.pop(); 106 } 107 else if(a==‘Q‘){ 108 int x=read(); 109 find(x); 110 if(val[root]==x) printf("0\n"); 111 112 else { 113 int succ=suc(x); 114 int pree=pre(x); 115 printf("%d\n",val[succ]-val[pree]-1); 116 } 117 } 118 } 119 }
先写了这两个题,慢慢来。。。。
原文:https://www.cnblogs.com/plysc/p/10382765.html