[模板]ETT

解:splay维护括号序列,就是进子树一次出子树一次。树上每个点直接记录这两个点的编号。

建树的时候按照分配的编号建树。

 

  1 #include <bits/stdc++.h>
  2 typedef long long LL;
  3 #define gc pa==pb&&(pb=(pa=buf)+fread(buf,1,100000,stdin),pa==pb)?EOF:*pa++
  4 static char buf[100000],*pa(buf),*pb(buf);
  5 template <class T> inline void read(T &x) {
  6     x = 0;
  7     register char c(gc);
  8     while((c<'0'||c>'9')&&c!='-')
  9         c=gc;
 10     register int f(c=='-'?c=gc,-1:1);
 11     while(c>='0'&&c<='9')
 12         x=x*10+c-48,c=gc;
 13     x*=f;
 14     return;
 15 }
 16 
 17 const int N = 400010;
 18 const LL INF = 0x3f3f3f3f3f3f3f3fll;
 19 
 20 struct Edge {
 21     int nex, v;
 22 }edge[N]; int tp;
 23 
 24 int fa[N], op[N], ed[N], s[N][2], root, stk[N], top;
 25 LL large[N], val[N], Val[N], tag[N];
 26 int e[N], num = 1, n, id[N];
 27 
 28 inline void add(int x, int y) {
 29     tp++;
 30     edge[tp].v = y;
 31     edge[tp].nex = e[x];
 32     e[x] = tp;
 33     return;
 34 }
 35 
 36 void DFS(int x, int f) {
 37     id[++num] = x;
 38     op[x] = num;
 39     for(int i = e[x]; i; i = edge[i].nex) {
 40         int y = edge[i].v;
 41         if(y == f) continue;
 42         DFS(y, x);
 43     }
 44     id[++num] = x;
 45     ed[x] = num;
 46     return;
 47 }
 48 
 49 inline void pushup(int x) {
 50     large[x] = std::max(large[s[x][0]], large[s[x][1]]);
 51     large[x] = std::max(large[x], val[x]);
 52     if(!fa[x]) root = x;
 53     return;
 54 }
 55 
 56 inline void pushdown(int x) {
 57     if(tag[x]) {
 58         if(s[x][0]) {
 59             tag[s[x][0]] += tag[x];
 60             val[s[x][0]] += tag[x];
 61             large[s[x][0]] += tag[x];
 62         }
 63         if(s[x][1]) {
 64             tag[s[x][1]] += tag[x];
 65             val[s[x][1]] += tag[x];
 66             large[s[x][1]] += tag[x];
 67         }
 68         tag[x] = 0;
 69     }
 70     return;
 71 }
 72 
 73 void out(int x = root) {
 74     pushdown(x);
 75     if(s[x][0]) {
 76         out(s[x][0]);
 77     }
 78     printf("%d ", id[x]);
 79     if(s[x][1]) {
 80         out(s[x][1]);
 81     }
 82     return;
 83 }
 84 
 85 inline void rotate(int x) {
 86     int y = fa[x];
 87     int z = fa[y];
 88     bool f = (s[y][1] == x);
 89     
 90     fa[x] = z;
 91     if(z) {
 92         s[z][s[z][1] == y] = x;
 93     }
 94     s[y][f] = s[x][!f];
 95     if(s[x][!f]) {
 96         fa[s[x][!f]] = y;
 97     }
 98     s[x][!f] = y;
 99     fa[y] = x;
100     
101     pushup(y);
102     return;
103 }
104 
105 inline void splay(int x, int g = 0) {
106     int y = x;
107     stk[top = 1] = y;
108     while(fa[y]) {
109         y = fa[y];
110         stk[++top] = y;
111     }
112     while(top) {
113         pushdown(stk[top]);
114         top--;
115     }
116     
117     y = fa[x];
118     int z = fa[y];
119     while(y != g) {
120         if(z != g) {
121             (s[z][1] == y) ^ (s[y][1] == x) ? 
122             rotate(x) : rotate(y);
123         }
124         rotate(x);
125         y = fa[x];
126         z = fa[y];
127     }
128     pushup(x);
129     return;
130 }
131 
132 inline int getLP() {
133     pushdown(root);
134     int p = s[root][0];
135     while(s[p][1]) {
136         p = s[p][1];
137         pushdown(p);
138     }
139     return p;
140 }
141 
142 inline int getRP() {
143     pushdown(root);
144     int p = s[root][1];
145     while(s[p][0]) {
146         p = s[p][0];
147         pushdown(p);
148     }
149     return p;
150 }
151 
152 int build(int l, int r, int f) {
153     int mid = (l + r) >> 1;
154     //int x = np(f, Val[id[mid]]);
155     fa[mid] = f;
156     val[mid] = large[mid] = Val[id[mid]];
157     if(l < mid) s[mid][0] = build(l, mid - 1, mid);
158     if(mid < r) s[mid][1] = build(mid + 1, r, mid);
159     pushup(mid);
160     return mid;
161 }
162 
163 inline void Add(int x, LL v) {
164     splay(op[x]);
165     int a = getLP();
166     splay(ed[x]);
167     int b = getRP();
168     splay(b);
169     splay(a, b);
170     int z = s[a][1];
171     tag[z] += v;
172     large[z] += v;
173     val[z] += v;
174     pushup(a);
175     pushup(b);
176     return;
177 }
178 
179 int main() {
180 
181     int q, rt, x; LL y;
182     read(n); read(q); read(rt);
183     for(register int i = 1; i <= n; i++) {
184         read(Val[i]);
185     }
186     for(register int i = 1; i < n; i++) {
187         read(x); read(y);
188         add(x, y); add(y, x);
189     }
190     
191     DFS(rt, 0);
192     
193     /*for(int i = 1; i <= num + 1; i++) {
194         printf("%d ", id[i]);
195     }
196     puts("");*/
197     
198     Val[0] = val[0] = -INF;
199     root = build(1, num + 1, 0);
200     
201     //out(), puts("");
202     
203     for(int i = 1, f; i <= q; i++) {
204         read(f); read(x);
205         if(f == 3) { /// out max subtree x
206             splay(op[x]);
207             int a = getLP();
208             splay(ed[x]);
209             int b = getRP();
210             splay(b);
211             splay(a, b);
212             printf("%lld\n", large[s[a][1]]);
213         }
214         else if(f == 2) { /// subtree x += y
215             read(y);
216             Add(x, y);
217         }
218         else if(f == 1) { /// change fa[x] -> y
219             read(y);
220             splay(op[x]);
221             int a = getLP();
222             splay(ed[x]);
223             int b = getRP();
224             
225             /*printf("%d op = %d ed = %d \n", x, op[x], ed[x]);
226             printf("a=%d %d  b=%d %d \n", a, id[a], b, id[b]);*/
227             
228             splay(b);
229             splay(a, b);
230             int z = s[a][1];
231             s[a][1] = fa[z] = 0;
232             pushup(a);
233             pushup(b);
234             splay(op[y]);
235             int t = getRP();
236             splay(t, op[y]);
237             s[t][0] = z; fa[z] = t;
238             pushup(t);
239             pushup(op[y]);
240         }
241         //out(), puts("");
242     }
243     
244     return 0;
245 }
AC代码

 

转载于:https://www.cnblogs.com/huyufeifei/p/10607106.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值