HDU 3966 Aragorn's Story (树链剖分 + 线段树)
2016-09-15 13:36
447 查看
题目点我点我点我
题目大意:
给一棵树,并给定各个点权的值,然后有3种操作:
I C1 C2 K: 把C1与C2的路径上的所有点权值加上K
D C1 C2 K:把C1与C2的路径上的所有点权值减去K
Q C:查询节点编号为C的权值
解题思路:第一道树链剖分orz,应该是算一道模版题吧……
发个树链剖分入门博客:传送门
题目大意:
给一棵树,并给定各个点权的值,然后有3种操作:
I C1 C2 K: 把C1与C2的路径上的所有点权值加上K
D C1 C2 K:把C1与C2的路径上的所有点权值减去K
Q C:查询节点编号为C的权值
解题思路:第一道树链剖分orz,应该是算一道模版题吧……
发个树链剖分入门博客:传送门
/* *********************************************** ┆ ┏┓ ┏┓ ┆ ┆┏┛┻━━━┛┻┓ ┆ ┆┃ ┃ ┆ ┆┃ ━ ┃ ┆ ┆┃ ┳┛ ┗┳ ┃ ┆ ┆┃ ┃ ┆ ┆┃ ┻ ┃ ┆ ┆┗━┓ 马 ┏━┛ ┆ ┆ ┃ 勒 ┃ ┆ ┆ ┃ 戈 ┗━━━┓ ┆ ┆ ┃ 壁 ┣┓┆ ┆ ┃ 的草泥马 ┏┛┆ ┆ ┗┓┓┏━┳┓┏┛ ┆ ┆ ┃┫┫ ┃┫┫ ┆ ┆ ┗┻┛ ┗┻┛ ┆ ************************************************ */ #include <stdio.h> #include <string.h> #include <iostream> #include <algorithm> #include <vector> #include <queue> #include <stack> #include <set> #include <map> #include <string> #include <math.h> #include <stdlib.h> #include <bitset> using namespace std; #define rep(i,a,b) for (int i=(a),_ed=(b);i<=_ed;i++) #define per(i,a,b) for (int i=(b),_ed=(a);i>=_ed;i--) #define pb push_back #define mp make_pair const int inf_int = 2e9; const long long inf_ll = 2e18; #define inf_add 0x3f3f3f3f #define mod 1000000007 #define LL long long #define ULL unsigned long long #define MS0(X) memset((X), 0, sizeof((X))) #define SelfType int SelfType Gcd(SelfType p,SelfType q){return q==0?p:Gcd(q,p%q);} SelfType Pow(SelfType p,SelfType q){SelfType ans=1;while(q){if(q&1)ans=ans*p;p=p*p;q>>=1;}return ans;} #define Sd(X) int (X); scanf("%d", &X) #define Sdd(X, Y) int X, Y; scanf("%d%d", &X, &Y) #define Sddd(X, Y, Z) int X, Y, Z; scanf("%d%d%d", &X, &Y, &Z) #define reunique(v) v.resize(std::unique(v.begin(), v.end()) - v.begin()) #define all(a) a.begin(), a.end() typedef pair<int, int> pii; typedef pair<long long, long long> pll; typedef vector<int> vi; typedef vector<long long> vll; inline int read(){int ra,fh;char rx;rx=getchar(),ra=0,fh=1;while((rx<'0'||rx>'9')&&rx!='-')rx=getchar();if(rx=='-')fh=-1,rx=getchar();while(rx>='0'&&rx<='9')ra*=10,ra+=rx-48,rx=getchar();return ra*fh;} //#pragma comment(linker, "/STACK:102400000,102400000") const int N =50005; int n,m,q; struct Edge { int to,nx; }edge[N*2]; int head ,cnt; void addedge(int u,int v) { edge[cnt] = Edge{v,head[u]}; head[u] = cnt++; } /*树链剖分*/ int top ,son ,dep ,siz ; int fa ,Rank ,tid ,tot; /* top[v]表示v所在的链的顶端节点, son[v]表示与v在同一重链上的v的儿子节点 dep[v]表示v的深度(根深度为1), siz[v]表示以v为根的子树的节点数, fa[v]表示v的父亲, rank[id]=v表示在线段树上编号为id的是节点v tid[v]表示在线段树上的编号 tot 表示编号 */ void dfs1(int u,int father,int d) { dep[u] = d; fa[u] = father; siz[u] = 1; for(int i=head[u];i;i=edge[i].nx) { int v = edge[i].to; if(v==father)continue; dfs1(v,u,d+1); siz[u] += siz[v]; if(son[u]==-1 || siz[v]>siz[son[u]]) son[u] = v; } } void dfs2(int u,int tp) { top[u] = tp; tid[u] = ++tot; Rank[tot] = u; if(son[u]==-1)return; dfs2(son[u],tp); for(int i=head[u];i;i=edge[i].nx) { int v = edge[i].to; if(v==fa[u] || v==son[u])continue; dfs2(v,v); } } /*线段树*/ int add[N*4],val ; void pushdown(int rt) { if(add[rt]) { add[rt<<1] += add[rt]; add[rt<<1|1] += add[rt]; add[rt] = 0; } } void build(int l,int r,int rt) { add[rt] = 0; if(l==r) { add[rt] = val[Rank[r]]; return; } int mid = (l+r) >> 1; build(l,mid,rt<<1); build(mid+1,r,rt<<1|1); } void update(int l,int r,int rt,int L,int R,int k) { if(L<=l && r<=R) { add[rt] += k; return; } pushdown(rt); int mid = (l+r) >> 1; if(L<=mid) update(l,mid,rt<<1,L,R,k); if(R>mid) update(mid+1,r,rt<<1|1,L,R,k); } int query(int l,int r,int rt,int x) { if(l==r)return add[rt]; pushdown(rt); int mid = (l+r) >> 1; if(x<=mid) return query(l,mid,rt<<1,x); else return query(mid+1,r,rt<<1|1,x); } void change(int x,int y,int k) { while(top[x]!=top[y]) { if(dep[top[x]]<dep[top[y]])swap(x,y); update(1,n,1,tid[top[x]],tid[x],k); x = fa[top[x]]; } if(dep[x]>dep[y])swap(x,y); update(1,n,1,tid[x],tid[y],k); } void init() { MS0(head); memset(son,-1,sizeof son); cnt = 1; tot = 0; } int main() { //freopen("in.txt","r",stdin); //freopen("out.txt","w",stdout); ios::sync_with_stdio(0); cin.tie(0); char s[5]; while(~scanf("%d%d%d",&n,&m,&q)) { init(); int a,b,c; for(int i=1;i<=n;i++) { scanf("%d",&val[i]); } for(int i=1;i<=m;i++) { int u,v; scanf("%d%d",&u,&v); addedge(u,v); addedge(v,u); } dfs1(1,0,0); dfs2(1,1); build(1,n,1); while(q--) { scanf("%s",s); if(s[0]=='Q') { scanf("%d",&a); printf("%d\n",query(1,n,1,tid[a])); } else { scanf("%d%d%d",&a,&b,&c); if(s[0]=='D')c = -c; change(a,b,c); } } } return 0; }
相关文章推荐
- HDU 3966 Aragorn's Story(树链剖分+线段树区间更新+手动扩大内存)
- hdu 3966 Aragorn's Story 树链剖分
- HDU 3966 Aragorn's Story(树链剖分)
- hdu 3966 Aragorn's Story(树链剖分+树状数组)
- Hdu 3966 Aragorn's Story 树链剖分+树状数组
- HDU 3966 Aragorn's Story(树链剖分)
- HDU 3966 Aragorn's Story(树链剖分)
- hdoj 3966 Aragorn's Story 【树链剖分+线段树||树状数组】
- HDU 3966 Aragorn's Story [树链剖分]
- HDU 3966 Aragorn's Story 树链剖分
- hdu-3966 Aragorn's Story(树链剖分,点权)
- Hdu 3966 Aragorn's Story (树链剖分 + 线段树区间更新)
- hdu 3966 Aragorn's Story 树链剖分
- HDU 3966 Aragorn's Story(树链剖分 点权,树状数组)
- hdu 3966 Aragorn's Story 树链剖分
- [hdu 3966 Aragorn's Story] 点权树链剖分
- HDU-3966-Aragorn's Story(树链剖分)
- hdu 3966 Aragorn's Story(树链剖分+树状数组)
- HDU 3966 Aragorn's Story (树链剖分 区间更新,点查询)
- hdu 3966 Aragorn's Story(树链剖分)