• 【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
    ",queryM(x,in()));
                else printf("%d
    ",queryS(x,in()));
            }
        }    
    }
    int main(){init();solve();return 0;}
  • 相关阅读:
    HashMap按键排序和按值排序
    LeetCode 91. Decode Ways
    LeetCode 459. Repeated Substring Pattern
    JVM
    LeetCode 385. Mini Parse
    LeetCode 319. Bulb Switcher
    LeetCode 343. Integer Break
    LeetCode 397. Integer Replacement
    LeetCode 3. Longest Substring Without Repeating Characters
    linux-网络数据包抓取-tcpdump
  • 原文地址:https://www.cnblogs.com/Melacau/p/BZOJ1036.html
Copyright © 2020-2023  润新知