zoj3765Lights(splay)

链接

splay的增删改操作。

刚开始对于某段区间首先有了lazy标记时,把其左右孩子给交换了,导致在pushup时又交换了一次而debug了n久。

  1 #include <iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<algorithm>
  5 #include<stdlib.h>
  6 #include<vector>
  7 #include<cmath>
  8 #include<queue>
  9 #include<set>
 10 using namespace std;
 11 #define N 300010
 12 #define LL long long
 13 #define INF 0xfffffff
 14 #define key_value ch[ch[root][1]][0]
 15 const double eps = 1e-8;
 16 const double pi = acos(-1.0);
 17 const double inf = ~0u>>2;
 18 using namespace std;
 19 int a[N][2];
 20 struct splay_tree
 21 {
 22     int pre[N],size[N],vv[N];
 23     int ch[N][2];
 24     int root,n,tot,num,tot1;
 25     int s[N][2],sta[N],key[N];
 26     void dfs(int x)
 27     {
 28         if(x)
 29         {
 30             dfs(ch[x][0]);
 31             printf("结点%2d:左儿子 %2d 右儿子 %2d 父结点 %2d size=%2d,key=%2d s0=%d  s1 = %d vv=%d\n",
 32                    x,ch[x][0],ch[x][1],pre[x],size[x],key[x],s[x][0],s[x][1],vv[x]);
 33             dfs(ch[x][1]);
 34         }
 35     }
 36     void debug()
 37     {
 38         printf("root:%d\n",root);
 39         dfs(root);
 40     }
 41 //以上用于debug*/
 42     void newnode(int &x,int v,int sta,int fa)//新建一结点
 43     {
 44         x = ++tot;
 45         ch[x][0]=ch[x][1] = 0;
 46         pre[x] = fa;
 47         s[x][0] = s[x][1] = 0;
 48         s[x][sta] = v;
 49         size[x] = 1;
 50         vv[x] = sta;
 51         key[x] = v;
 52     }
 53     void pushup(int w)//由儿子更新其父亲
 54     {
 55         size[w] = size[ch[w][0]]+size[ch[w][1]]+1;
 56         int st = vv[w];
 57         int l = ch[w][0],r = ch[w][1];
 58         int cnt1 = 0,cnt2 = 0;
 59         cnt1 = s[l][0];
 60         if(s[r][0])
 61         {
 62             if(cnt1) cnt1 = __gcd(s[r][0],cnt1);
 63             else cnt1 = s[r][0];
 64         }
 65         cnt2 = s[l][1];
 66         if(s[r][1])
 67         {
 68             if(cnt2) cnt2 = __gcd(s[r][1],cnt2);
 69             else cnt2 = s[r][1];
 70         }
 71         s[w][0] = cnt1,s[w][1] = cnt2;
 72         s[w][st] = s[w][st]?__gcd(s[w][st],key[w]):key[w];
 73         //cout<<s[w][0]<<" "<<s[w][1]<<endl;
 74     }
 75     void rotate(int r,int kind)//旋转操作,根据kind进行左旋和右旋
 76     {
 77         int y = pre[r];
 78         ch[y][!kind] = ch[r][kind];
 79         pre[ch[r][kind]] = y;
 80         if(pre[y])
 81         {
 82             ch[pre[y]][ch[pre[y]][1]==y] = r;
 83         }
 84         pre[r] = pre[y];
 85         ch[r][kind] = y;
 86         pre[y] = r;
 87         pushup(y);
 88         pushup(r);
 89     }
 90     void splay(int r,int goal)//将r结点旋至goal下
 91     {
 92         while(pre[r]!=goal)
 93         {
 94             if(pre[pre[r]]==goal)
 95             {
 96                 rotate(r,ch[pre[r]][0]==r);
 97             }
 98             else
 99             {
100                 int y = pre[r];
101                 int kind = (ch[pre[y]][0]==y);
102                 if(ch[y][kind]==r)
103                 {
104                     rotate(r,!kind);
105                     rotate(r,kind);
106                 }
107                 else
108                 {
109                     rotate(y,kind);
110                     rotate(r,kind);
111                 }
112             }
113         }
114         pushup(r);
115         if(goal==0) root = r;
116     }
117     int get_k(int k)//得到第k个的结点
118     {
119         int r = root;
120         while(size[ch[r][0]]+1!=k)
121         {
122             if(size[ch[r][0]]>=k)
123                 r = ch[r][0];
124             else
125             {
126                 k-=(size[ch[r][0]]+1);//根据左右结点的数量来确定第k个节点在哪里
127                 r = ch[r][1];
128             }
129         }
130         pushup(r);
131         return r;
132     }
133     void add(int k,int val,int sta)//添加一个结点 位置自己修改 这里为第一个
134     {
135         splay(get_k(k),0);
136         splay(get_k(k+1),root);
137         int r = ch[root][1];
138         newnode(ch[r][0],val,sta,r);
139         pushup(r);
140         pushup(root);
141     }
142     void updelete(int r)//删除第r个结点
143     {
144         splay(get_k(r),0);
145         splay(get_k(r+2),root);
146         key_value = 0;
147         pushup(ch[root][1]);
148         pushup(root);
149     }
150     void update(int k,int flag,int v) //更新区间信息
151     {
152         splay(get_k(k),0);
153         splay(get_k(k+2),root);
154         if(flag)
155         {
156             vv[key_value]^=1;
157             swap(s[key_value][1],s[key_value][0]);
158         }
159         else
160         {key[key_value] = v;s[key_value][vv[key_value]] = v;}
161         pushup(ch[root][1]);
162         pushup(root);
163
164     }
165     int query(int l,int r,int sta)//询问l,r区间,将第l-1个结点旋自根,第r+1个结点旋自根的有儿子,
166     {
167         //则l-r就变成了根的右儿子的左儿子
168         splay(get_k(l),0);
169         splay(get_k(r+2),root);
170         return s[key_value][sta];
171     }
172     void build(int &x,int l,int r,int fa)
173     {
174         int m = (l+r)>>1;
175         if(l>r) return ;
176         newnode(x,a[m][0],a[m][1],fa);
177         build(ch[x][0],l,m-1,x);
178         build(ch[x][1],m+1,r,x);
179         pushup(x);
180     }
181     void init(int o)
182     {
183         int i;
184         for(i = 1; i <= o; i++)
185         scanf("%d%d",&a[i][0],&a[i][1]);
186         size[0] = ch[0][0] = ch[0][1] = s[0][0] = s[0][1] = key[0] = vv[0] = 0;
187         root = tot = 0;
188         newnode(root,0,0,0);
189         newnode(ch[root][1],0,0,root);
190         build(ch[ch[root][1]][0],1,o,ch[root][1]);
191         size[root] = 2;
192         pushup(ch[root][1]);
193         pushup(root);
194     }
195 }SP;
196 int main()
197 {
198     int n,q;
199     while(scanf("%d%d",&n,&q)!=EOF)
200     {
201         SP.init(n);
202         while(q--)
203         {
204             char sq[20];
205             int k,x,y;
206             scanf("%s%d",sq,&k);
207             if(sq[0]==‘I‘)
208             {
209                 scanf("%d%d",&x,&y);
210                 SP.add(k+1,x,y);
211                // SP.debug();
212             }
213             else if(sq[0]==‘D‘)
214             {
215                 SP.updelete(k);
216             }
217             else if(sq[0]==‘R‘)
218             {
219                 SP.update(k,1,0);
220             }
221             else if(sq[0]==‘M‘)
222             {
223                 scanf("%d",&x);
224                 SP.update(k,0,x);
225             }
226             else if(sq[0]==‘Q‘)
227             {
228                 scanf("%d%d",&x,&y);
229                 int ans = SP.query(k,x,y);
230                 if(ans==0)
231                 printf("-1\n");
232                 else
233                 printf("%d\n",ans);
234                // SP.debug();
235             }
236         }
237     }
238     return 0;
239 }

zoj3765Lights(splay),布布扣,bubuko.com

时间: 2024-09-29 20:46:45

zoj3765Lights(splay)的相关文章

BZOJ 1861 [Zjoi2006]Book 书架 ——Splay

[题目分析] 模板题目. 首尾两个虚拟结点,十分方便操作. [代码] #include <cstdio> #include <cstring> #include <cmath> #include <cstdlib> #include <map> #include <set> #include <queue> #include <string> #include <iostream> #include

及其简短的Splay代码

#include <stdio.h> #include <queue> #include <algorithm> #include <stdlib.h> #include <math.h> #include <iostream> #define inf 1000000000 using namespace std; #define getch() getchar() inline int F() {register int aa ,

BZOJ_1014_[JSOI2008]_火星人prefix_(Splay+LCP_Hash+二分)

描述 http://www.lydsy.com/JudgeOnline/problem.php?id=1014 给出一个字符串,有修改,插入,以及询问LCP(i,j)的操作. 分析 LCP在白书上面有介绍,\(LCP(i,j)\)表示以第\(i\)位和以第\(j\)位开头的后缀的最长公共前缀. 先考虑没有插入和修改操作的问题.我们可以用基于Hash的LCP算法. 我们给每一个后缀一个Hash值.其中以第\(i\)为开头的后缀的Hash值为\(H[i]=H[i+1]x+s[i]\). 其中\(x\

BZOJ 1251 序列终结者(Splay)

题目大意 网上有许多题,就是给定一个序列,要你支持几种操作:A.B.C.D.一看另一道题,又是一个序列要支持几种操作:D.C.B.A.尤其是我们这里的某人,出模拟试题,居然还出了一道这样的,真是没技术含量……这样 我也出一道题,我出这一道的目的是为了让大家以后做这种题目有一个“库”可以依靠,没有什么其他的意思.这道题目 就叫序列终结者吧.[问题描述] 给定一个长度为N的序列,每个序列的元素是一个整数(废话).要支持以下三种操作: 1. 将 [L, R] 这个区间内的所有数加上 V. 2. 将 [

CSU 1555 Inversion Sequence 给出逆序数求排列 splay

题目链接:点击打开链接 题意: 给出逆序数的值,求原序列(一个1-N的排列) 1, 2, 0, 1, 0 表示1的逆序数是1,2的逆序数是2,3的逆序数是0··· 思路: 从最后一个数开始插,每次插到当前序列的第a[i]个数.. splay模拟 == 这个方法比较直(wu)观(nao),别的方法并没有想出来.. #include <cstdio> #include <iostream> #include <cstring> #include <queue>

【UOJ】【UR #2】猪猪侠再战括号序列(splay/贪心)

http://uoj.ac/problem/31 纪念伟大的没有调出来的splay... 竟然那个find那里写错了!!!!!!!!!!!!! 以后要记住:一定要好好想过! (正解的话我就不写了,太简单了.. #include <cstdio> #include <cstring> #include <cmath> #include <string> #include <iostream> #include <algorithm> #

BZOJ 1507 NOI2003 Editor Splay

题目大意: 1.将光标移动到某一位置 2.在光标后插入一段字符串 3.删除光标后的一段字符 4.输出光标后的一段字符 5.光标-- 6.光标++ 和1269很像的一道题,不过弱多了 几个问题需要注意: 1.插入的字符串中间居然会有回车!!没办法了,只能逐个字符进行读入,一旦读到'\n'或者'\r'就重新读入 2.题目描述中说Delete和Get操作后面一定会有足够的字符 纯属放P 连样例都没有足够的字符用来删除 所以删除时要和字符串长度取一个最小值 然后就水水地过去了~ 30%达成 今天是不是可

【Splay】【启发式合并】hdu6133 Army Formations

题意:给你一颗树,每个结点的儿子数不超过2.每个结点有一个权值,一个结点的代价被定义为将其子树中所有结点的权值放入数组排序后,每个权值乘以其下标的和.让你计算所有结点的代价. 二叉树的条件没有用到. 每个结点开一个Splay,从叶子往上启发式合并上去,可以先bfs一遍确定合并顺序.每一次将Splay大小较小的结点的权值全提取出来塞到较大的里面. 由于权值可能重复出现,所以每个结点记个cnt. 答案统计的时候,就将那个刚塞进去的旋到根,然后答案加上左子树的权值和,再加上(右子树的权值的个数+该结点

数组splay ------ luogu P3369 【模板】普通平衡树(Treap/SBT)

二次联通门 : luogu P3369 [模板]普通平衡树(Treap/SBT) #include <cstdio> #define Max 100005 #define Inline __attri\ bute__( ( optimize( "-O2" ) ) ) Inline void read (int &now) { now = 0; register char word = getchar (); bool temp = false; while (wor