BZOJ 4034: [HAOI2015]树上操作 [欧拉序列 线段树]
题意:
操作 1 :把某个节点 x 的点权增加 a 。
操作 2 :把某个节点 x 为根的子树中所有点的点权都增加 a 。
操作 3 :询问某个节点 x 到根的路径中所有点的点权和。
显然树链剖分可做,但我是来练欧拉序列的
和splay维护一样了
其实没大有意义....如果树形态不改变人家树链剖分本来就可以维护子树信息....
唯一的好处就是不会爆栈吧
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> using namespace std; #define lc x<<1 #define rc x<<1|1 #define mid ((l+r)>>1) #define lson lc, l, mid #define rson rc, mid+1, r #define pii pair<int, int> #define MP make_pair #define fir first #define sec second typedef long long ll; const int N=2e5+5; inline int read(){ char c=getchar();int x=0,f=1; 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; } int n, Q, op, x, y, a[N]; struct edge{int v, ne;} e[N<<1]; int cnt, h[N]; inline void ins(int u, int v) { e[++cnt]=(edge){v, h[u]}; h[u]=cnt; e[++cnt]=(edge){u, h[v]}; h[v]=cnt; } pii dfn[N]; int dfc, eul[N]; void dfs(int u, int fa) { dfn[u].fir = ++dfc; eul[dfc] = u; for(int i=h[u]; i; i=e[i].ne) if(e[i].v != fa) dfs(e[i].v, u); dfn[u].sec = ++dfc; eul[dfc] = -u; } struct SegTre { struct meow{ll sum, tag; int sl, sr;} t[N<<2]; inline void merge(int x) { t[x].sum = t[lc].sum + t[rc].sum; t[x].sl = t[lc].sl + t[rc].sl; t[x].sr = t[lc].sr + t[rc].sr; } inline void paint(int x, ll v) { t[x].sum += (t[x].sl - t[x].sr)*v; t[x].tag += v; } inline void pushDown(int x) { if(t[x].tag) { paint(lc, t[x].tag); paint(rc, t[x].tag); t[x].tag = 0; } } void build(int x, int l, int r) { if(l==r) { if(eul[l] > 0) t[x].sum = a[eul[l]], t[x].sl = 1; else t[x].sum = -a[-eul[l]], t[x].sr = 1; }else { build(lson); build(rson); merge(x); } } void Add(int x, int l, int r, int p, int v) { if(l==r) paint(x, v); else { pushDown(x); if(p<=mid) Add(lson, p, v); else Add(rson, p, v); merge(x); } } void Add2(int x, int l, int r, int ql, int qr, ll v) { if(ql<=l && r<=qr) paint(x, v); else { pushDown(x); if(ql<=mid) Add2(lson, ql, qr, v); if(mid<qr) Add2(rson, ql, qr, v); merge(x); } } ll Que(int x, int l, int r, int ql, int qr) { if(ql<=l && r<=qr) return t[x].sum; else { pushDown(x); ll ans=0; if(ql<=mid) ans += Que(lson, ql, qr); if(mid<qr) ans += Que(rson, ql, qr); return ans; } } }seg; int main() { freopen("in","r",stdin); n=read(); Q=read(); for(int i=1; i<=n; i++) a[i]=read(); for(int i=1; i<n; i++) x=read(), y=read(), ins(x, y); dfs(1, 0); seg.build(1, 1, dfc); for(int i=1; i<=Q; i++) { op=read(); x=read(); if(op==3) printf("%lld\n", seg.Que(1, 1, dfc, dfn[1].fir, dfn[x].fir)); else{ y=read(); if(op==1) seg.Add(1, 1, dfc, dfn[x].fir, y), seg.Add(1, 1, dfc, dfn[x].sec, y); else seg.Add2(1, 1, dfc, dfn[x].fir, dfn[x].sec, y); } } }
Copyright:http://www.cnblogs.com/candy99/