[國家集訓隊]Tree II
阿新 • • 發佈:2018-12-22
rotate turn ostream void ret == wap cst tdi
嘟嘟嘟
這道題其實還是挺基礎的,只不過操作有點多。
區間乘和區間加按線段樹的方式想。
那麽就先要下放乘標記,再下放加標記。但這兩個和反轉標記是沒有先後順序的。
對於區間加,sum加的是區間長度\(*\)lazy標記。但是線段樹區間固定,而lct不是,所以還要單獨維護一個size。
還有一點,這個是splay的性質,就是當前節點的sum還要算上自己的權值,而不像線段樹完全由子樹信息合並而來。
最最最後一點,得開long long,包括點權。
#include<cstdio> #include<iostream> #include<cmath> #include<algorithm> #include<cstring> #include<cstdlib> #include<cctype> #include<vector> #include<stack> #include<queue> using namespace std; #define enter puts("") #define space putchar(‘ ‘) #define Mem(a, x) memset(a, x, sizeof(a)) #define In inline typedef long long ll; typedef double db; const int INF = 0x3f3f3f3f; const db eps = 1e-8; const int maxn = 1e5 + 5; const ll mod = 51061; inline ll read() { ll ans = 0; char ch = getchar(), last = ‘ ‘; while(!isdigit(ch)) last = ch, ch = getchar(); while(isdigit(ch)) ans = (ans << 1) + (ans << 3) + ch - ‘0‘, ch = getchar(); if(last == ‘-‘) ans = -ans; return ans; } inline void write(ll x) { if(x < 0) x = -x, putchar(‘-‘); if(x >= 10) write(x / 10); putchar(x % 10 + ‘0‘); } int n, q; char c[2]; struct Tree { int ch[2], fa; int siz, rev; ll val, sum, add, mul; }t[maxn]; In void c_rev(int now) { swap(t[now].ch[0], t[now].ch[1]); t[now].rev ^= 1; } In void c_mul(int now, ll lzy) { t[now].sum *= lzy; t[now].sum %= mod; t[now].val *= lzy; t[now].val %= mod; t[now].mul *= lzy; t[now].mul %= mod; t[now].add *= lzy; t[now].add %= mod; } In void c_add(int now, ll lzy) { t[now].sum += lzy * (ll)t[now].siz; t[now].sum %= mod; t[now].val += lzy; t[now].val %= mod; t[now].add += lzy; t[now].add %= mod; } In void pushdown(int now) { if(t[now].rev) { if(t[now].ch[0]) c_rev(t[now].ch[0]); if(t[now].ch[1]) c_rev(t[now].ch[1]); t[now].rev = 0; } if(t[now].mul != 1) { if(t[now].ch[0]) c_mul(t[now].ch[0], t[now].mul); if(t[now].ch[1]) c_mul(t[now].ch[1], t[now].mul); t[now].mul = 1; } if(t[now].add) { if(t[now].ch[0]) c_add(t[now].ch[0], t[now].add); if(t[now].ch[1]) c_add(t[now].ch[1], t[now].add); t[now].add = 0; } } In void pushup(int now) { t[now].siz = t[t[now].ch[0]].siz + t[t[now].ch[1]].siz + 1; t[now].sum = (t[t[now].ch[0]].sum + t[t[now].ch[1]].sum + t[now].val) % mod; } In bool n_root(int now) { return t[t[now].fa].ch[0] == now || t[t[now].fa].ch[1] == now; } In void rotate(int x) { int y = t[x].fa, z = t[y].fa, k = (t[y].ch[1] == x); if(n_root(y)) t[z].ch[t[z].ch[1] == y] = x; t[x].fa = z; t[y].ch[k] = t[x].ch[k ^ 1]; t[t[y].ch[k]].fa = y; t[x].ch[k ^ 1] = y; t[y].fa = x; pushup(y), pushup(x); } int st[maxn], top = 0; In void splay(int x) { int y = x; st[top = 1] = y; while(n_root(y)) st[++top] = y = t[y].fa; while(top) pushdown(st[top--]); while(n_root(x)) { int y = t[x].fa, z = t[y].fa; if(n_root(y)) rotate(((t[y].ch[0] == x) ^ (t[z].ch[0] == y)) ? x : y); rotate(x); } } In void access(int x) { int y = 0; while(x) { splay(x); t[x].ch[1] = y; pushup(x); y = x; x = t[x].fa; } } In void make_root(int x) { access(x); splay(x); c_rev(x); } In int find_root(int x) { access(x); splay(x); while(t[x].ch[0]) pushdown(x), x = t[x].ch[0]; return x; } In void split(int x, int y) { make_root(x); access(y); splay(y); } In void Link(int x, int y) { make_root(x); if(find_root(y) != x) t[x].fa = y; } In void Cut(int x, int y) { make_root(x); if(find_root(y) == x && t[x].fa == y && !t[x].ch[1]) t[y].ch[0] = t[x].fa = 0, pushup(y); } int main() { n = read(); q = read(); for(int i = 1; i <= n; ++i) t[i].val = t[i].mul = t[i].siz = 1; for(int i = 1, x, y; i < n; ++i) x = read(), y = read(), Link(x, y); for(int i = 1; i <= q; ++i) { scanf("%s", c); int x = read(), y = read(); if(c[0] == ‘+‘) {int d = read(); split(x, y); c_add(y, d);} else if(c[0] == ‘*‘) {int d = read(); split(x, y); c_mul(y, d);} else if(c[0] == ‘/‘) split(x, y), write(t[y].sum), enter; else { Cut(x, y); x = read(), y = read(); Link(x, y); } } return 0; }
[國家集訓隊]Tree II