P3178 [HAOI2015]树上操作 树链剖分
这个题就是一道树链剖分的裸题,但是需要有一个魔性操作___编号数组需要开longlong!!!震惊!真的神奇.
题干:
题目描述 有一棵点数为 N 的树,以点 1 为根,且树点有边权。然后有 M 个操作,分为三种:操作 1 :把某个节点 x 的点权增加 a 。操作 2 :把某个节点 x 为根的子树中所有点的点权都增加 a 。操作 3 :询问某个节点 x 到根的路径中所有点的点权和。 输入输出格式 输入格式: 第一行包含两个整数 N, M 。表示点数和操作数。接下来一行 N 个整数,表示树中节点的初始权值。接下来 N-1 行每行两个正整数 from, to , 表示该树中存在一条边 (from, to) 。再接下来 M 行,每行分别表示一次操作。其中第一个数表示该操作的种类( 1-3 ) ,之后接这个操作的参数( x 或者 x a ) 。 输出格式: 对于每个询问操作,输出该询问的答案。答案之间用换行隔开。 输入输出样例 输入样例#1: 复制 5 5 1 2 3 4 5 1 2 1 4 2 3 2 5 3 3 1 2 1 3 5 2 1 2 3 3 输出样例#1: 复制 6 9 13 说明 对于 100% 的数据, N,M<=100000 ,且所有输入数据的绝对值都不 会超过 10^6 。
代码:
#include<iostream> #include<cstdio> #include<cmath> #include<ctime> #include<queue> #include<algorithm> #include<cstring> using namespace std; #define duke(i,a,n) for(int i = a;i <= n;i++) #define lv(i,a,n) for(int i = a;i >= n;i--) #define clean(a) memset(a,0,sizeof(a)) const int INF = 1 << 30; typedef long long ll; typedef double db; template <class T> void read(T &x) { char c; bool op = 0; while(c = getchar(), c < '0' || c > '9') if(c == '-') op = 1; x = c - '0'; while(c = getchar(), c >= '0' && c <= '9') x = x * 10 + c - '0'; if(op) x = -x; } template <class T> void write(T x) { if(x < 0) putchar('-'), x = -x; if(x >= 10) write(x / 10); putchar('0' + x % 10); } const int N = 200010; struct node { ll l,r; int nxt; }a[N]; int len = 0,lst[N]; void add(ll x,ll y) { a[++len].l = x; a[len].r = y; a[len].nxt = lst[x]; lst[x] = len; } ll n,m; ll tree[N << 2],lazy[N << 2]; ll siz[N],son[N],cnt = 0,id[N]; ll A[N]; ll top[N],f[N],rk[N],dep[N]; int vis[N]; void dfs1(ll u,ll fa,ll depth) { f[u] = fa; siz[u] = 1; dep[u] = depth; for(int k = lst[u];k;k = a[k].nxt) { ll y = a[k].r; if(y == fa) continue; dfs1(y,u,depth + 1); siz[u] += siz[y]; if(!son[u] || siz[son[u]] < siz[y]) son[u] = y; } } void dfs2(ll u,ll t) { vis[u] = 1; top[u] = t; id[u] = ++cnt; rk[cnt] = u; if(!son[u]) return; dfs2(son[u],t); for(int k = lst[u];k;k = a[k].nxt) { ll y = a[k].r; if(y == son[u] || y == f[u] || vis[y] == 1) continue; dfs2(y,y); } } void build(ll o,ll l,ll r) { if(l == r) { tree[o] = A[rk[l]]; return; } ll mid = (l + r) >> 1; build(o << 1,l,mid); build(o << 1 | 1,mid + 1,r); tree[o] = tree[o << 1] + tree[o << 1 | 1]; } void push_down(ll o,ll l,ll r) { if(lazy[o] != 0) { ll mid = (l + r) >> 1; tree[o << 1] += (ll)(mid - l + 1) * lazy[o]; tree[o << 1 | 1] += (ll)(r - mid) * lazy[o]; lazy[o << 1] += lazy[o]; lazy[o << 1 | 1] += lazy[o]; lazy[o] = 0; } } void sin_change(ll o,ll l,ll r,ll k,ll w) { if(l == r) { tree[o] += w; lazy[o] += w; return; } ll mid = (l + r) >> 1; push_down(o,l,r); if(mid >= k) sin_change(o << 1,l,mid,k,w); else sin_change(o << 1 | 1,mid + 1,r,k,w); } void all_change(ll o,ll l,ll r,ll x,ll y,ll w) { if(l == x && r == y) { tree[o] += (r - l + 1) * w; lazy[o] += w; return; } push_down(o,l,r); ll mid = (l + r) >> 1; if(mid >= y) all_change(o << 1,l,mid,x,y,w); else if(mid < x) all_change(o << 1 | 1,mid + 1,r,x,y,w); else { all_change(o << 1,l,mid,x,mid,w); all_change(o << 1 | 1,mid + 1,r,mid + 1,y,w); } tree[o] = tree[o << 1] + tree[o << 1 | 1]; } ll query(ll o,ll l,ll r,ll x,ll y) { if(l == x && r == y) return tree[o]; push_down(o,l,r); ll mid = (l + r) >> 1; if(mid >= y) return query(o << 1,l,mid,x,y); else if(mid < x) return query(o << 1 | 1,mid + 1,r,x,y); else { ll ans = 0; ans += query(o << 1,l,mid,x,mid); ans += query(o << 1 | 1,mid + 1,r,mid + 1,y); return ans; } } ll work(int x,int y) { ll ans = 0; while(top[x] != top[y]) { if(dep[top[x]] < dep[top[y]]) swap(x,y); ll res = query(1,1,n,id[top[x]],id[x]); ans += res; x = f[top[x]]; } if(dep[x] > dep[y]) swap(x,y); ans += query(1,1,n,id[x],id[y]); return ans; } int main() { read(n);read(m); duke(i,1,n) read(A[i]); duke(i,1,n - 1) { ll x,y; read(x);read(y); add(x,y); add(y,x); } dfs1(1,0,1); dfs2(1,1); int ok; build(1,1,n); /*duke(i,1,n) printf("%d ",top[i]); cout<<endl;*/ /*duke(i,1,n) printf("%d ",tree[i]); cout<<endl;*/ duke(i,1,m) { read(ok); if(ok == 1) { ll x;ll y; read(x);read(y); all_change(1,1,n,id[x],id[x],y); } else if(ok == 2) { ll x;ll y; read(x);read(y); all_change(1,1,n,id[x],id[x] + siz[x] - 1,y); } else { ll x; read(x);//printf("!!!%d %d\n",id[1],id[x]); printf("%lld\n",work(1,x)); } /*duke(i,1,n) printf("%d ",lazy[i]); cout<<endl;*/ } return 0; } /* 5 5 1 2 3 4 5 1 2 1 4 2 3 2 5 3 3 1 2 1 3 5 2 1 2 3 3 */
只想找一个不会伤害我的人