1. 程式人生 > >BZOJ3531 樹剖 + 動態開點線段樹

BZOJ3531 樹剖 + 動態開點線段樹

code std ring bsp node -- amp eps 容易

https://www.lydsy.com/JudgeOnline/problem.php?id=3531

首先這題意要求樹鏈上的最大值以及求和,其樹鏈剖分的做法已經昭然若揭

問題在於這次的信息有宗教條件下的限制,導致不那麽容易維護。

第一個想法自然是對於每一個宗教都建一顆線段樹,看一下數據範圍,宗教的範圍是1e5,N的範圍也是1e5,又好像空間不那麽允許。

事實上可以采用動態線段樹的方法節省一波空間,整個做法就變得科學了起來。

如果不是因為我的愚蠢在樹剖的重鏈部分寫掛了導致T了很久,這題還是很溫暖的

#include <map>
#include <set
> #include <ctime> #include <cmath> #include <queue> #include <stack> #include <vector> #include <string> #include <cstdio> #include <cstdlib> #include <cstring> #include <sstream> #include <iostream> #include <algorithm> #include
<functional> using namespace std; #define For(i, x, y) for(int i=x;i<=y;i++) #define _For(i, x, y) for(int i=x;i>=y;i--) #define Mem(f, x) memset(f,x,sizeof(f)) #define Sca(x) scanf("%d", &x) #define Sca2(x,y) scanf("%d%d",&x,&y) #define Sca3(x,y,z) scanf("%d%d%d",&x,&y,&z) #define
Scl(x) scanf("%lld",&x); #define Pri(x) printf("%d\n", x) #define Prl(x) printf("%lld\n",x); #define CLR(u) for(int i=0;i<=N;i++)u[i].clear(); #define LL long long #define ULL unsigned long long #define mp make_pair #define PII pair<int,int> #define PIL pair<int,long long> #define PLL pair<long long,long long> #define pb push_back #define fi first #define se second typedef vector<int> VI; int read(){int x = 0,f = 1;char c = getchar();while (c<0 || c>9){if (c == -) f = -1;c = getchar();} while (c >= 0&&c <= 9){x = x * 10 + c - 0;c = getchar();}return x*f;} const double eps = 1e-9; const int maxn = 1e5 + 10; const int INF = 0x3f3f3f3f; const int mod = 1e9 + 7; int N,M,K; inline int max(int a,int b){ return a>b?a:b; } PII node[maxn]; struct Edge{ int to,next; }edge[maxn * 2]; int head[maxn],Tot; void init(){ for(int i = 0 ; i <= N ; i ++) head[i] = -1; Tot = 0; } void add(int u,int v){ edge[Tot].to = v; edge[Tot].next = head[u]; head[u] = Tot++; } int size[maxn],top[maxn],fa[maxn],son[maxn]; int dep[maxn],pos[maxn]; void dfs(int t,int la){ size[t] = 1; son[t] = 0; int heavy = 0; for(int i = head[t]; ~i ; i = edge[i].next){ int v = edge[i].to; if(v == la) continue; fa[v] = t; dep[v] = dep[t] + 1; dfs(v,t); if(heavy < size[v]){ heavy = size[v]; son[t] = v; } size[t] += size[v]; } } int cnt; void dfs2(int t,int la){ top[t] = la; pos[t] = ++cnt; if(!son[t]) return; dfs2(son[t],la); for(int i = head[t]; ~i ; i = edge[i].next){ int v = edge[i].to; if(fa[t] == v || son[t] == v) continue; dfs2(v,v); } } struct Tree{ int Max,sum; int lt,rt; void init(){ Max = sum = lt = rt = 0; } }tree[maxn * 60]; int tot; int thead[maxn]; void check(int &t){ if(t) return; t = ++tot; tree[t].init(); } void Pushup(int t){ int ls = tree[t].lt,rs = tree[t].rt; check(ls);check(rs); tree[t].sum = tree[ls].sum + tree[rs].sum; tree[t].Max = max(tree[ls].Max,tree[rs].Max); } void update(int &t,int l,int r,int p,int w){ check(t); if(l == r){ tree[t].Max = tree[t].sum = w; return; } int m = (l + r) >> 1; if(p <= m) update(tree[t].lt,l,m,p,w); else update(tree[t].rt,m + 1,r,p,w); Pushup(t); } void update(int i,int w){ update(thead[node[i].se],1,N,pos[i],w); } int query(int &t,int l,int r,int L,int R,int p){ check(t); if(L <= l && r <= R){ if(p) return tree[t].sum; else return tree[t].Max; } int m = (l + r) >> 1; if(R <= m) return query(tree[t].lt,l,m,L,R,p); else if(L > m) return query(tree[t].rt,m + 1,r,L,R,p); else{ if(p) return query(tree[t].lt,l,m,L,m,p) + query(tree[t].rt,m + 1,r,m + 1,R,p); else return max(query(tree[t].lt,l,m,L,m,p),query(tree[t].rt,m + 1,r,m + 1,R,p)); } } int query(int u,int v,int flag){ int ans = 0; int &c = thead[node[u].se]; while(top[u] != top[v]){ if(dep[top[u]] < dep[top[v]]) swap(u,v); if(flag) ans += query(c,1,N,pos[top[u]],pos[u],1); else ans = max(ans,query(c,1,N,pos[top[u]],pos[u],0)); u = fa[top[u]]; } if(dep[u] > dep[v]) swap(u,v); if(flag) ans += query(c,1,N,pos[u],pos[v],1); else ans = max(ans,query(c,1,N,pos[u],pos[v],0)); return ans; } int main(){ Sca2(N,M); init(); for(int i = 1; i <= N ; i ++) node[i].fi = read(),node[i].se = read(); for(int i = 1; i <= N - 1; i ++){ int u = read(),v = read(); add(u,v); add(v,u); } int root = 1; dfs(root,0); dfs2(root,root); for(int i = 1; i <= N; i ++) update(i,node[i].fi); for(int i = 1; i <= M ; i ++){ char op[5]; scanf("%s",op); int x = read(),y = read(); if(op[0] == C){ if(op[1] == C){ update(x,0); node[x].se = y; update(x,node[x].fi); }else{ node[x].fi = y; update(x,y); } }else{ if(op[1] == S){ Pri(query(x,y,1)); //sum }else{ Pri(query(x,y,0)); //Max } } } return 0; }

BZOJ3531 樹剖 + 動態開點線段樹