zoukankan      html  css  js  c++  java
  • [LUOGU] P4178 Tree

    用树状数组维护f前缀和,复杂度O(nlog^2n),冲榜第一

    为什么大家都用的容斥、可并堆、平衡树...

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    
    using namespace std;
    
    inline int rd(){
        int ret=0,f=1;char c;
        while(c=getchar(),!isdigit(c))f=c=='-'?-1:1;
        while(isdigit(c))ret=ret*10+c-'0',c=getchar();
        return ret*f;
    }
    
    const int MAXN=200005;
    const int INF=1<<29;
    
    int n,m;
    
    struct Edge{
        int next,to,w;
    }e[MAXN<<1];
    int ecnt,head[MAXN];
    inline void add(int x,int y,int w){
        e[++ecnt].next = head[x];
        e[ecnt].to = y;
        e[ecnt].w = w;
        head[x] = ecnt;
    }
    
    int t[MAXN];
    void update(int x,int val){
        for(int i=x;i<=m;i+=i&-i)t[i]+=val;
    }
    int query(int x){
        if(x==0) return 0;
        int ret=0;
        for(int i=x;i;i-=i&-i)ret+=t[i];
        return ret;
    }
    
    bool vis[MAXN];
    
    int siz[MAXN];
    void getsiz(int x,int pre){
        siz[x]=1;
        for(int i=head[x];i;i=e[i].next){
            int v=e[i].to;
            if(vis[v]||v==pre) continue;
            getsiz(v,x);
            siz[x]+=siz[v];
        }
    }
    int mn=INF,root;
    void getroot(int x,int pre,int tot){
        int mx=0;
        for(int i=head[x];i;i=e[i].next){
            int v=e[i].to;
            if(vis[v]||v==pre) continue;
            mx=max(mx,siz[v]);
            getroot(v,x,tot);
        }
        mx=max(mx,tot-siz[x]);
        if(mx<mn) mn=mx,root=x;
    }
    int s[MAXN],sav[MAXN];
    
    void dfs(int x,int pre,int dis){
        if(dis>m) return;
        s[++s[0]]=dis;sav[++sav[0]]=dis;
        for(int i=head[x];i;i=e[i].next){
            int v=e[i].to;
            if(vis[v]||v==pre) continue;
            dfs(v,x,dis+e[i].w);
        }
    }
    
    int ans;
    
    void dac(int x){//Divide and Conquer :)
        sav[0]=0;mn=n;
        getsiz(x,-1);
        getroot(x,-1,siz[x]);
        int u=root;vis[u]=1;
        for(int i=head[u];i;i=e[i].next){
            int v=e[i].to;
            if(vis[v]) continue;
            s[0]=0;dfs(v,u,e[i].w); 
            for(int j=s[0];j>=1;j--){
                if(s[j]>m) continue;
                ans+=query(m-s[j]);
            }
            for(int j=s[0];j>=1;j--){
                if(s[j]>m) continue;
                update(s[j],1);
                ans++;
            }
        }
        for(int i=sav[0];i>=1;i--){
            if(sav[i]>m) continue;
            update(sav[i],-1);
        }
        for(int i=head[u];i;i=e[i].next){
            int v=e[i].to;
            if(vis[v]) continue;
            dac(v);
        }
    }
            
    int main(){
        n=rd();
        int x,y,w;
        for(int i=1;i<n;i++){
            x=rd();y=rd();w=rd();
            add(x,y,w);add(y,x,w);
        }
        m=rd();
        dac(1);
        cout<<ans;
        return 0;
    }

    本文来自博客园,作者:GhostCai,转载请注明原文链接:https://www.cnblogs.com/ghostcai/p/9477437.html

  • 相关阅读:
    深入理解计算机操作系统(十)
    深入理解计算机操作系统(九)
    深入理解计算机操作系统(八)
    深入理解计算机操作系统(七)
    深入理解计算机操作系统(六)
    深入理解计算机操作系统(五)
    mysql创建新用户
    沙特女性终于开车上路,仍有男性对此不爽
    为什么人们爱听有声书?
    韩流来袭,英文歌曲的垄断地位被撼动
  • 原文地址:https://www.cnblogs.com/ghostcai/p/9477437.html
Copyright © 2011-2022 走看看