BZOJ 1036 [ZJOI2008]树的统计Count
2016-08-01 22:08
423 查看
首先树链剖分。
要支持求极值,求和,修改,把所有树链加入线段树进行维护即可。
要支持求极值,求和,修改,把所有树链加入线段树进行维护即可。
#include<cstdio> #include<algorithm> #define MAXN 30010 using namespace std; struct edge{int next,to;}e[MAXN*2]; struct segment{int sum, maxx, l, r;}node[MAXN*10]; const int INF = 1000000000; int cnt=0; int last[MAXN], siz[MAXN], son[MAXN], top[MAXN], fa[MAXN], dep[MAXN], w[MAXN]; int tree[MAXN], pre[MAXN], tcnt=0; void add(int a,int b){e[++cnt]=(edge){last[a],b};last[a]=cnt;} void build(int x, int l, int r) { node[x].l=l; node[x].r=r; if(l==r) { node[x].sum=node[x].maxx=w[pre[l]]; return; } int mid=(l+r)>>1; build(x<<1,l,mid); build(x<<1|1,mid+1,r); node[x].sum=node[x<<1].sum+node[x<<1|1].sum; node[x].maxx=max(node[x<<1].maxx,node[x<<1|1].maxx); } int ask_sum(int x, int l, int r) { if(r<node[x].l||node[x].r<l) return 0; if(l<=node[x].l&&node[x].r<=r) return node[x].sum; int mid=(node[x].l+node[x].r)>>1; int ret=0; if(l<=mid)ret+=ask_sum(x<<1,l,r); if(mid+1<=r)ret+=ask_sum(x<<1|1,l,r); return ret; } int ask_max(int x, int l, int r) { if(r<node[x].l||node[x].r<l) return -INF; if(l<=node[x].l&&node[x].r<=r) return node[x].maxx; int mid=(node[x].l+node[x].r)>>1; int ret=-INF; if(mid>=l)ret=max(ret,ask_max(x<<1,l,r)); if(mid+1<=r)ret=max(ret,ask_max(x<<1|1,l,r)); return ret; } void dfs1(int x) { dep[x]=dep[fa[x]]+1; siz[x]=1; for(int i = last[x]; i; i=e[i].next) { int y=e[i].to; if(fa[x]!=y) { fa[y]=x; dfs1(y); siz[x]+=siz[y]; if(siz[y]>siz[son[x]]) son[x]=y; } } } void dfs2(int x) { if(son[fa[x]]==x) top[x]=top[fa[x]]; else top[x]=x; tree[x]=++tcnt; pre[tcnt]=x; if(son[x])dfs2(son[x]); for(int i = last[x]; i; i=e[i].next) if(e[i].to!=fa[x] && e[i].to!=son[x]) dfs2(e[i].to); } int qmax(int a, int b) { int ret=-INF; while(top[a]!=top[b]) { if(dep[top[a]]<dep[top[b]]) swap(a,b); ret=max(ret,ask_max(1,tree[top[a]],tree[a])); a=fa[top[a]]; } if(dep[b]>dep[a])swap(a,b); return max(ret,ask_max(1,tree[b],tree[a])); } int qsum(int a, int b) { int ret=0; while(top[a]!=top[b]) { if(dep[top[a]]<dep[top[b]]) swap(a,b); ret+=ask_sum(1,tree[top[a]],tree[a]); a=fa[top[a]]; } if(dep[b]>dep[a])swap(a,b); return ret+ask_sum(1,tree[b],tree[a]); } void update(int x, int p) { if(node[x].l==node[x].r) { node[x].sum=node[x].maxx=w[pre[node[x].l]]; return; } int mid=(node[x].l+node[x].r)>>1; if(p<=mid)update(x<<1,p); else update(x<<1|1,p); node[x].sum=node[x<<1].sum+node[x<<1|1].sum; node[x].maxx=max(node[x<<1].maxx,node[x<<1|1].maxx); } void change(int a, int b) { w[a]=b; update(1,tree[a]); } int main() { int n; scanf("%d",&n); for(int i = 1; i < n; i++) { int a, b; scanf("%d%d",&a,&b); add(a,b); add(b,a); } for(int i = 1; i <= n; i++) scanf("%d",&w[i]); dfs1(1); dfs2(1); build(1,1,n); int q; scanf("%d",&q); for(;q--;) { char s[10]; int a, b; scanf("%s%d%d",s,&a,&b); if(s[1]=='M') printf("%d\n",qmax(a,b)); else if(s[1]=='S') printf("%d\n",qsum(a,b)); else change(a,b); } return 0; }
相关文章推荐
- 【lct】bzoj1036 [ZJOI2008]树的统计Count
- bzoj 1036 [ZJOI2008]树的统计Count 线段树+树链剖分
- bzoj1036 [ZJOI2008]树的统计Count
- bzoj 1036: [ZJOI2008]树的统计Count(树链剖分)
- 1036: [ZJOI2008]树的统计Count - BZOJ
- BZOJ 1036: [ZJOI2008]树的统计Count
- bzoj 1036: [ZJOI2008]树的统计Count 树链剖分+线段树
- [BZOJ1036][ZJOI2008]树的统计Count
- bzoj1036: [ZJOI2008]树的统计Count(树链剖分)
- 【bzoj1036】【树链剖分】【ZJOI2008】树的统计Count
- [BZOJ 1036] ZJOI 2008 树的统计Count · 树链剖分
- BZOJ1036 [ZJOI2008]树的统计Count(树链剖分)
- [BZOJ1036][ZJOI2008]树的统计Count(树链剖分)
- BZOJ 1036: [ZJOI2008]树的统计Count 树链剖分
- BZOJ 1036: [ZJOI2008]树的统计Count 树链剖分+线段树
- bzoj1036 [ZJOI2008]树的统计Count
- 【BZOJ1036】[ZJOI2008]树的统计Count 树链剖分
- BZOJ 1036 [ZJOI2008]树的统计Count 树链剖分
- 【bzoj 1036】 [ZJOI2008]树的统计Count
- 树链剖分初讲 && [bzoj1036][ZJOI2008]树的统计Count