[BZOJ 3786] 星系探索 Splay维护入栈出栈序

题意

  给定一棵 n 个节点, 点有点权, 以 1 为根的有根树.

  m 次操作:

    ① 查询点 d 到根的点权之和.

    ② 将 x 及其子树截出来, 作为 y 的儿子.

    ③ 将以 p 为根的子树的点权增加 q .

  $n \le 100000$ .

实现

  1 #include <cstdio>
  2 #include <cstring>
  3 #include <cstdlib>
  4 #include <cctype>
  5 #include <vector>
  6 using namespace std;
  7 #define F(i, a, b) for (register int i = (a); i <= (b); i++)
  8 #define LL long long
  9 inline int rd(void) {
 10     int f = 1; char c = getchar(); for (; !isdigit(c); c = getchar()) if (c == ‘-‘) f = -1;
 11     int x = 0; for (; isdigit(c); c = getchar()) x = x*10+c-‘0‘; return x*f;
 12 }
 13 inline char rdc(void) { char c = getchar(); for (; !isalpha(c); c = getchar()); return c; }
 14
 15 const int N = 200005;
 16
 17 #define fore(it, x) for (register vector<int>::iterator it = g[x].begin(); it != g[x].end(); it++)
 18 int n, w[N];
 19 vector<int> g[N];
 20
 21 int tot, List[N], In[N], Out[N];
 22 void Prework(int x) {
 23     List[++tot] = x, In[x] = tot;
 24     fore(it, x)
 25         Prework(*it);
 26     List[++tot] = x, Out[x] = tot;
 27 }
 28
 29 #define LC (c[x][0])
 30 #define RC (c[x][1])
 31
 32 int rt, c[N][2], par[N];
 33 LL key[N], sign[N], cnt[N], sum[N], tag[N];
 34
 35 inline void Pushup(int x) { cnt[x] = cnt[LC] + cnt[RC] + sign[x], sum[x] = sum[LC] + sum[RC] + key[x] * sign[x]; }
 36 inline void Push(int x, LL t) { key[x] += t, sum[x] += cnt[x] * t, tag[x] += t; }
 37 inline void Clear(int x) {
 38     if (!tag[x]) return;
 39     if (LC > 0) Push(LC, tag[x]);
 40     if (RC > 0) Push(RC, tag[x]);
 41     tag[x] = 0;
 42 }
 43
 44 inline void Rot(int x) {
 45     int t = par[x];
 46     int L = (c[t][1] == x), R = L^1;
 47
 48     if (par[t] > 0)
 49         c[par[t]][c[par[t]][1] == t] = x;
 50     par[x] = par[t];
 51
 52     if (c[x][R] > 0)
 53         par[c[x][R]] = t;
 54     c[t][L] = c[x][R];
 55
 56     c[x][R] = t, par[t] = x;
 57     Pushup(t), Pushup(x);
 58 }
 59 inline void Splay(int x, int f = 0) {
 60     static int L[N]; int tot = 0;
 61     L[++tot] = x;
 62     for (int i = x; par[i] != f; i = par[i]) L[++tot] = par[i];
 63     for (; tot > 0; L[tot--] = 0)
 64         Clear(L[tot]);
 65
 66     for (; par[x] != f; Rot(x)) {
 67         int y = par[x], z = par[y];
 68         if (z != f && par[z] != f) (c[z][0] == y) ^ (c[y][0] == x) ? Rot(x) : Rot(y);
 69     }
 70     if (!f) rt = x;
 71 }
 72
 73 void Build(int &x, int L, int R) {
 74     x = (L+R)>>1;
 75     if (List[x] > 0)
 76         sign[x] = (In[List[x]] == x ? 1 : -1), key[x] = w[List[x]];
 77     if (L < x) Build(LC, L, x-1), par[LC] = x;
 78     if (x < R) Build(RC, x+1, R), par[RC] = x;
 79     Pushup(x);
 80 }
 81
 82 inline int Pre(int x) {
 83     // Find Pre(x) and Splay it to Root !
 84     Splay(x);
 85     int y = LC; while (c[y][1] > 0) y = c[y][1];
 86     Splay(y);
 87     return y;
 88 }
 89 inline int Nxt(int x) {
 90     Splay(x);
 91     int y = RC; while (c[y][0] > 0) y = c[y][0];
 92     Splay(y);
 93     return y;
 94 }
 95
 96 inline LL Query(int di) {
 97     int x = Nxt(In[di]);
 98     Splay(x);
 99     return sum[LC];
100 }
101 inline void Depend(int xi, int yi) {
102     int L = Pre(In[xi]);
103     int R = Nxt(Out[xi]);
104     Splay(L);
105     Splay(R);
106     int x = c[rt][0], y = c[x][1];
107     c[x][1] = par[y] = 0, Pushup(x), Pushup(rt);
108
109     L = In[yi], R = Nxt(In[yi]);
110     Splay(L);
111     Splay(R);
112     x = c[rt][0];
113     c[x][1] = y, par[y] = x, Pushup(x), Pushup(rt);
114 }
115 inline void Inspire(int pi, int qi) {
116     int L = Pre(In[pi]);
117     int R = Nxt(Out[pi]);
118     Splay(L);
119     Splay(R);
120     int x = c[rt][0], y = c[x][1];
121     Push(y, qi);
122     Pushup(x), Pushup(rt);
123 }
124
125 void Get(int x) { if (!x) return; Clear(x); Get(LC); printf("%lld ", key[x]); Get(RC); }
126 void Print(int x) { Get(x); puts(""); }
127
128 int main(void) {
129     #ifndef ONLINE_JUDGE
130         freopen("bzoj3786.in", "r", stdin);
131         //  freopen("bzoj3786.out", "w", stdout);
132     #endif
133
134     n = rd();
135     F(i, 2, n) g[rd()].push_back(i);
136     F(i, 1, n) w[i] = rd();
137
138     List[++tot] = 0, In[0] = tot;
139     Prework(1);
140     List[++tot] = 0, Out[0] = tot;
141
142     Build(rt, 1, 2*n+2);
143     // [1, 2n+2]
144
145     int m = rd();
146     F(nC, 1, m) {
147         char c = rdc();
148         if (c == ‘Q‘) {
149             int di = rd();
150             printf("%lld\n", Query(di));
151         }
152         else if (c == ‘C‘) {
153             int xi = rd(), yi = rd();
154             Depend(xi, yi);
155         }
156         else {
157             int pi = rd(), qi = rd();
158             Inspire(pi, qi);
159         }
160     }
161
162     return 0;
163 }
时间: 2025-01-16 03:59:14

[BZOJ 3786] 星系探索 Splay维护入栈出栈序的相关文章

BZOJ 3786 星系探索 Splay维护树的入栈出栈序

题目大意:给出一棵树,要求有以下这些操作:1.求出一个节点到根的点权和.2.将一个节点的父亲改变.3.将一个子树中的每一个节点都加上一个权值. 思路:LCT就不用想了,因为有子树操作.然后就是一个很神奇的东西了,就是Splay维护树的入栈出栈序.这个玩应是做了这个题之后才知道的.但是感觉真的很dio. 首先,我们先按照题意,将树建出来.然后从根开始深搜,这样一个点进入DFS函数和出DFS函数的时候就会有两个时间点,就是入栈的时间和出栈的时间.然后利用Splay维护一个序列,就是入栈出栈的顺序.在

bzoj 3786 星系探索 (splay+dfs序)

题目大意:给你一棵树,支持一下三种操作 1.获取某节点到根节点的路径上所有节点的权值和 2.更换某棵子树的父亲 3.某子树内所有节点的权值都增加一个值w 当时想到了splay维护dfs序,查完题解发现思路是对的,然后我就写了足足6个小时才A st[x]代表入栈时间,ed[x]代表出栈时间 对于第一个操作,每个树上节点在splay中都有两个位置,分别对应入栈出栈序,然后把入栈的点权*1,出栈点权*-1,就可以避免其它子树干扰了 接着查询到根节点的路径权值和呢,splay把1~st[x]整个序列都扔

BZOJ 3786 星系探索 DFS序+Splay

题目大意:给定一棵有根树,提供下列操作: 1.询问某个点到根路径上的点权和 2.修改某个点的父亲,保证修改之后仍然是一棵树 3.将某个点所在子树的所有点权加上一个值 子树修改,LCT明显是搞不了了,在想究竟会不会有人去写自适应Top-Tree-- 首先我们DFS搞出这棵树的入栈出栈序 然后入栈为正出栈为负 那么一个点到根的路径上的点权和就是从根节点的入栈位置到这个点的入栈位置的和 子树修改就记录某段序列中有多少入栈和多少出栈,然后根据这个对这棵子树所在序列修改即可 那么换父亲操作呢?显然可以用S

bzoj 3786 星系探索 dfs+splay

[BZOJ3786]星系探索 Description 物理学家小C的研究正遇到某个瓶颈. 他正在研究的是一个星系,这个星系中有n个星球,其中有一个主星球(方便起见我们默认其为1号星球),其余的所有星球均有且仅有一个依赖星球.主星球没有依赖星球. 我们定义依赖关系如下:若星球a的依赖星球是b,则有星球a依赖星球b.此外,依赖关系具有传递性,即若星球a依赖星球b,星球b依赖星球c,则有星球a依赖星球c. 对于这个神秘的星系中,小C初步探究了它的性质,发现星球之间的依赖关系是无环的.并且从星球a出发只

BZOJ 3786 星系探索

Description 物理学家小C的研究正遇到某个瓶颈. 他正在研究的是一个星系,这个星系中有n个星球,其中有一个主星球(方便起见我们默认其为1号星球),其余的所有星球均有且仅有一个依赖星球.主星球没有依赖星球. 我们定义依赖关系如下:若星球a的依赖星球是b,则有星球a依赖星球b.此外,依赖关系具有传递性,即若星球a依赖星球b,星球b依赖星球c,则有星球a依赖星球c. 对于这个神秘的星系中,小C初步探究了它的性质,发现星球之间的依赖关系是无环的.并且从星球a出发只能直接到达它的依赖星球b. 每

【BZOJ-3786】星系探索 Splay + DFS序

3786: 星系探索 Time Limit: 40 Sec  Memory Limit: 256 MBSubmit: 647  Solved: 212[Submit][Status][Discuss] Description 物理学家小C的研究正遇到某个瓶颈. 他正在研究的是一个星系,这个星系中有n个星球,其中有一个主星球(方便起见我们默认其为1号星球),其余的所有星球均有且仅有一个依赖星球.主星球没有依赖星球. 我们定义依赖关系如下:若星球a的依赖星球是b,则有星球a依赖星球b.此外,依赖关系

bzoj3786星系探索 splay

3786: 星系探索 Time Limit: 40 Sec  Memory Limit: 256 MBSubmit: 1314  Solved: 425[Submit][Status][Discuss] Description 物理学家小C的研究正遇到某个瓶颈. 他正在研究的是一个星系,这个星系中有n个星球,其中有一个主星球(方便起见我们默认其为1号星球),其余的所有星球均有且仅有一个依赖星球.主星球没有依赖星球. 我们定义依赖关系如下:若星球a的依赖星球是b,则有星球a依赖星球b.此外,依赖关

顺序栈的初始化入栈出栈以及打印栈的信息

使用的开发工具CLion CLion 2017.2.1 Build #CL-172.3544.40, built on August 2, 2017Licensed to CLion EvaluatorExpiration date: September 15, 2017JRE: 1.8.0_152-release-915-b6 x86_64JVM: OpenJDK 64-Bit Server VM by JetBrains s.r.oMac OS X 10.12.4   1 #include

压栈出栈遍历栈实例代码

#include<stdio.h> #include<stdlib.h> #include<malloc.h> typedef struct Node//定义一个链表结构体 { int data; struct Node* pNext; }NODE,*PNODE; typedef struct Stack//定义一个栈结构体 { PNODE pTop; PNODE pBottom; }STACK,*PSTACK; void initStack(PSTACK); void