BZOJ 1036 [ZJOI2008] 树的统计Count (树链剖分)
2015-05-05 00:12
387 查看
题目地址:BZOJ 1036
树链剖分裸题,需要用线段树同时维护最大值与和值两个信息,只是代码量大一点而已。。
代码如下:
树链剖分裸题,需要用线段树同时维护最大值与和值两个信息,只是代码量大一点而已。。
代码如下:
#include <iostream> #include <string.h> #include <math.h> #include <queue> #include <algorithm> #include <stdlib.h> #include <map> #include <set> #include <stdio.h> using namespace std; #define LL long long #define pi acos(-1.0) //#pragma comment(linker, "/STACK:1024000000") const int mod=1e9+7; const int INF=0x3f3f3f3f; const double eqs=1e-3; const int MAXN=30000+10; #define root 1, tot, 1 #define lson l, mid, rt<<1 #define rson mid+1, r, rt<<1|1 int head[MAXN], cnt, tot; int siz[MAXN], top[MAXN], fa[MAXN], w[MAXN], son[MAXN], dep[MAXN]; int Max[MAXN<<2], sum[MAXN<<2]; struct node { int v, next; }edge[MAXN<<1]; void add(int u, int v) { edge[cnt].v=v; edge[cnt].next=head[u]; head[u]=cnt++; } void init() { memset(head,-1,sizeof(head)); cnt=tot=0; memset(dep,0,sizeof(dep)); memset(son,0,sizeof(son)); memset(Max,-INF,sizeof(Max)); memset(sum,0,sizeof(sum)); } void dfs1(int u, int p) { siz[u]=1; for(int i=head[u];i!=-1;i=edge[i].next){ int v=edge[i].v; if(v==p) continue ; dep[v]=dep[u]+1; fa[v]=u; dfs1(v,u); siz[u]+=siz[v]; if(siz[son[u]]<siz[v]) son[u]=v; } } void dfs2(int u, int tp) { w[u]=++tot; top[u]=tp; if(son[u]) dfs2(son[u],tp); for(int i=head[u];i!=-1;i=edge[i].next){ int v=edge[i].v; if(v!=fa[u]&&v!=son[u]) dfs2(v,v); } } struct Line_Tree { void PushUp(int rt) { Max[rt]=max(Max[rt<<1],Max[rt<<1|1]); sum[rt]=sum[rt<<1]+sum[rt<<1|1]; } void Update(int p, int x, int l, int r, int rt) { if(l==r){ Max[rt]=sum[rt]=x; return ; } int mid=l+r>>1; if(p<=mid) Update(p,x,lson); else Update(p,x,rson); PushUp(rt); } int MaxQuery(int ll, int rr, int l, int r, int rt) { if(ll<=l&&rr>=r){ return Max[rt]; } int mid=l+r>>1, ans=-INF; if(ll<=mid) ans=max(ans,MaxQuery(ll,rr,lson)); if(rr>mid) ans=max(ans,MaxQuery(ll,rr,rson)); return ans; } int SumQuery(int ll, int rr, int l, int r, int rt) { if(ll<=l&&rr>=r){ return sum[rt]; } int mid=l+r>>1, ans=0; if(ll<=mid) ans+=SumQuery(ll,rr,lson); if(rr>mid) ans+=SumQuery(ll,rr,rson); return ans; } }lt; int MaxSolve(int u, int v) { int f1=top[u], f2=top[v], ans=-INF; while(f1!=f2){ if(dep[f1]<dep[f2]){ swap(u,v); swap(f1,f2); } ans=max(ans,lt.MaxQuery(w[f1],w[u],root)); u=fa[f1];f1=top[u]; } if(dep[u]<dep[v]){ swap(u,v); } return max(ans,lt.MaxQuery(w[v],w[u],root)); } int SumSolve(int u, int v) { int f1=top[u], f2=top[v], ans=0; while(f1!=f2){ if(dep[f1]<dep[f2]){ swap(u,v); swap(f1,f2); } ans+=lt.SumQuery(w[f1],w[u],root); u=fa[f1];f1=top[u]; } if(dep[u]<dep[v]){ swap(u,v); } return ans+lt.SumQuery(w[v],w[u],root); } int main() { int n, i, u, v, c, q, id; char s[10]; while(scanf("%d",&n)!=EOF){ init(); for(i=1;i<n;i++){ scanf("%d%d",&u,&v); add(u,v); add(v,u); } dfs1(1,-1); dfs2(1,1); for(i=1;i<=n;i++){ scanf("%d",&c); lt.Update(w[i],c,root); } scanf("%d",&q); while(q--){ scanf("%s",s); if(s[1]=='M'){ scanf("%d%d",&u,&v); printf("%d\n",MaxSolve(u,v)); } else if(s[1]=='S'){ scanf("%d%d",&u,&v); printf("%d\n",SumSolve(u,v)); } else{ scanf("%d%d",&id,&c); lt.Update(w[id],c,root); } } } return 0; }
相关文章推荐
- BZOJ 1036: [ZJOI2008]树的统计Count 【树链剖分】
- 【BZOJ1036】[ZJOI2008]树的统计Count 树链剖分
- BZOJ 1036 [ZJOI2008]树的统计Count 树链剖分裸题
- |BZOJ 1036|树链剖分|线段树|[ZJOI2008]树的统计Count
- BZOJ1036 [ZJOI2008]树的统计Count(树链剖分)
- bzoj 1036: [ZJOI2008]树的统计Count——树链剖分
- BZOJ 1036: [ZJOI2008]树的统计Count 树链剖分
- 【BZOJ1036】[ZJOI2008]树的统计Count 树链剖分
- 树链剖分(bzoj 1036: [ZJOI2008]树的统计Count)
- BZOJ.1036 [ZJOI2008]树的统计Count ( 点权树链剖分 线段树维护和与最值)
- [bzoj1036][ZJOI2008]树的统计Count 树链剖分
- kyeremal-bzoj1036[ZJOI2008]-树的统计count-树链剖分
- bzoj 1036 [ZJOI2008]树的统计Count (树链剖分 + 线段树)
- [树链剖分] BZOJ1036: [ZJOI2008]树的统计Count
- bzoj 1036: [ZJOI2008]树的统计Count(树链剖分)
- BZOJ 1036: [ZJOI2008]树的统计Count(树链剖分)
- bzoj 1036: [ZJOI2008]树的统计Count(树链剖分)
- bzoj1036 [ZJOI2008]树的统计Count (树链剖分|Link Cut Tree)
- BZOJ 1036 [ZJOI2008]树的统计Count (树链剖分裸题)
- BZOJ 1036 [ZJOI2008]树的统计Count 树链剖分练手题