zoukankan      html  css  js  c++  java
  • 【NOIP2017提高组模拟7.3】B

    树上路径统计,点分治解决。

    统计一段区间,naive地用了set解决,这样的复杂度是O(nlog^2n)的

    考场代码出了个问题,统计答案时找到了之前的最优答案,但是没有加上新的一段,导致60分

    #include<iostream>
    #include<cstdio>
    #include<set>
    
    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 = 100005;
    
    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 n,L,R;
    
    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(v==pre||vis[v]) continue;
            getsiz(v,x);
            siz[x]+=siz[v];
        }
    }
    int mn,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(v==pre||vis[v]) continue;
            mx=max(mx,siz[v]);
            getroot(v,x,tot);
        }
        mx=max(mx,tot-siz[x]);
        if(mx<mn) root=x,mn=mx;
    }
    set<int> se;
    int s[MAXN];
    
    void dfs(int x,int pre,int dis){
        if(dis>R) return;//
        s[++s[0]]=dis;
        for(int i=head[x];i;i=e[i].next){
            int v=e[i].to;
            if(v==pre||vis[v]) continue;
            dfs(v,x,dis+e[i].w);
        }
    }
    
    int ans=1<<30;
    
    void dac(int x){
        mn=n;
        getsiz(x,-1);
        getroot(x,-1,siz[x]);
        int u=root;vis[u]=1;
        se.clear();
        se.insert(1<<30); 
        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--){
                int tmp=*se.lower_bound(L-s[j]);
                tmp+=s[j];
                if(tmp<ans&&tmp<=R&&tmp>=L) ans=tmp;
            }
            for(int j=s[0];j>=1;j--){
                if(s[j]<ans&&s[j]<=R&&s[j]>=L) ans=s[j];
                se.insert(s[j]);
            }
        }
        
        for(int i=head[u];i;i=e[i].next){
            int v=e[i].to;
            if(!vis[v]) dac(v);
        }
    }
                
    
    int main(){
        n=rd();L=rd();R=rd();
        int x,y,w;
        for(int i=1;i<=n-1;i++){
            x=rd();y=rd();w=rd();
            add(x,y,w);add(y,x,w);
        }
        dac(1);
        if(ans==1<<30) cout<<-1;
        else cout<<ans;
        return 0;
    }

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

  • 相关阅读:
    多线程锁--怎么理解Condition
    ThreadPoolExecutor
    ThreadFactory
    java内部类的初始化
    Android Private Libraries 和 Dependencies的区别
    Android严苛模式StrictMode使用详解
    [法律法规]《网络安全等级保护条例(征求意见稿)》
    [法律法规]中华人民共和国网络安全法
    Sqlserver tablediff的简单使用
    Sqlserver 命令行方式修改 用户密码的方法
  • 原文地址:https://www.cnblogs.com/ghostcai/p/9483574.html
Copyright © 2011-2022 走看看