【BZOJ1036】【ZJOI2008】数的统计

接着找树剖的题。。。传送门(点我)

题意:给你一棵无根树,有三种操作:查询树上2点路径的点权和/最大点权;更改某点的点权。

解题思路:树链剖分裸题,我采用了常数较小的zkw线段树维护剖下来的树(毕竟线段树常数太大很危险),然后就是树剖的东西解决即可。

时间复杂度:期望:\( O(n \log \log^{2} n) \) 最坏:\( O(n \log^{2} n) \)

AC代码:(1452ms,3144KB on BZOJ)

#include <stdio.h>
#define inf 0x7fffffff
#define MN 30005
#define Mn 32768
#define v (edge[i].to)
inline int in(){
    int x=0,f=1; char ch=getchar();
    while(ch<'0'||ch>'9') f=ch=='-'?-1:1,ch=getchar();
    while(ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
    return x*f;
}inline int max(int a,int b){return a>b?a:b;}
struct zxy{int to,nxt;}edge[MN<<1];
int top[MN],sum[Mn<<1],ma[Mn<<1],siz[MN],dep[MN],son[MN],fa[MN],pos[MN],head[MN],cnt,dfsn,n,q,M;
inline void ins(int x,int y){edge[++cnt].to=y,edge[cnt].nxt=head[x],head[x]=cnt;}
inline void dfs1(int u,int f,int d){
    dep[u]=d,fa[u]=f,siz[u]=1;
    for (register int i=head[u]; i; i=edge[i].nxt)
        if (v!=f){
            dfs1(v,u,d+1);siz[u]+=siz[v];
            if (siz[v]>siz[son[u]]) son[u]=v;
        }
}
inline void dfs2(int u,int tp){
    pos[u]=(++dfsn);top[u]=tp;if (son[u]) dfs2(son[u],tp);
    for (register int i=head[u]; i; i=edge[i].nxt)    
        if (v!=fa[u]&&v!=son[u]) dfs2(v,v);
}
inline void combine(int x){sum[x]=sum[x<<1]+sum[x<<1|1];ma[x]=max(ma[x<<1],ma[x<<1|1]);}
inline void A(int x,int k){sum[x+=M]=k,ma[x]=k;for (x>>=1; x; x>>=1) combine(x);}
inline int QM(int l,int r){
    register int res=-inf;
    for (l+=M-1,r+=M+1; l^r^1; l>>=1,r>>=1){
        if (~l&1) res=max(res,ma[l^1]);
        if (r&1) res=max(res,ma[r^1]);    
    }return res;
}
inline int QS(int l,int r){
    register int res=0;
    for (l+=M-1,r+=M+1; l^r^1; l>>=1,r>>=1){
        if (~l&1) res+=sum[l^1];
        if (r&1) res+=sum[r^1];
    }return res;
}
inline int queryS(int x,int y){
    register int res=0;
    while(top[x]!=top[y])
        if (dep[top[x]]>dep[top[y]]) res+=QS(pos[top[x]],pos[x]),x=fa[top[x]];
        else res+=QS(pos[top[y]],pos[y]),y=fa[top[y]];
    if (dep[x]<dep[y]) res+=QS(pos[x],pos[y]);
    else res+=QS(pos[y],pos[x]);return res;            
}
inline int queryM(int x,int y){
    register int res=-inf;
    while(top[x]!=top[y])
        if (dep[top[x]]>dep[top[y]]) res=max(res,QM(pos[top[x]],pos[x])),x=fa[top[x]];
        else res=max(res,QM(pos[top[y]],pos[y])),y=fa[top[y]];
    if (dep[x]<dep[y]) res=max(res,QM(pos[x],pos[y]));
    else res=max(res,QM(pos[y],pos[x]));return res;    
    return res;            
}
void init(){
    n=in();for (int i=1; i<n; ++i){
        register int x=in(),y=in();
        ins(x,y);ins(y,x);
    }
    dfs1(1,1,1);dfs2(1,1);for (M=1; M<n+2; M<<=1);
    for (register int i=1; i<=n; ++i)sum[M+pos[i]]=ma[M+pos[i]]=in();
    for (register int i=M; i; --i) combine(i);
}
void solve(){
    q=in();while(q--){
        register char op[10];scanf("%s",op);register int x=in();
        if (op[0]=='C') A(pos[x],in());
        else{
            if (op[1]=='M') printf("%d\n",queryM(x,in()));
            else printf("%d\n",queryS(x,in()));
        }
    }    
}
int main(){init();solve();return 0;}

 

posted @ 2017-04-25 16:50  Melacau  阅读(248)  评论(0编辑  收藏  举报