zoukankan      html  css  js  c++  java
  • 【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;}
  • 相关阅读:
    ASP程序调用验证码
    fcex pf.conf
    高速INTERNET代理服务器解决方案
    《IIS 6的几个经典问答》
    一个符合WEB标准的横向下拉菜单
    FREEBSD+PF 在6.2上的架设
    权限
    FreeBSD+IPFILTER实现整网(N个Vlan)透明代理上网
    pf 带宽控制 例子
    FreeBSD下配置DHCP服务小结
  • 原文地址:https://www.cnblogs.com/Melacau/p/BZOJ1036.html
Copyright © 2011-2022 走看看