• bzoj1758 [Wc2010]重建计划


    传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=1758

    【题解】

    一看就知道是分数规划问题就二分了。

    权值全部扣去二分的值x,转成判断是否存在L<=len<=U的路径,权值和>=0

    这就是一个点分的问题了。

    已经有一个二分了所以里面的点分只允许有一个log。我们需要线性合并这玩意儿。。

    我们想到了单调队列,我们很容易合并两个大小为深度的数组。

    然后想都不想直接交了一发,TLE?

    (这时候确实是对的)

    然后看了看网上的题解,因为二分过程中,每次点分的root是一样的,一直找很麻烦,所以我们可以提前处理好这个root。

    第一发写在了二分判断里了(那跟没写一样),后来写对完交了已发,还是TLE?

    打开discuss一看,这个加强数据的人怎么这样啊,不过也好,给了我很深的印象,以后会注意到这个的。

    写点分治的时候,如果合并涉及到子树合并,且合并的两个数组的大小为子树的深度和总深度,那么需要按子树深度从小到大合并。

    这样才能保证复杂度,其实这个tips之前有看到过(做codechef的primedst的时候)

    那么这么写完就过了,加了快读27s,这卡常题。。。卧槽怎么5k了。。

    # include <vector>
    # include <stdio.h>
    # include <string.h>
    # include <iostream>
    # include <algorithm>
    // # include <bits/stdc++.h>
    
    using namespace std;
    
    typedef long long ll;
    typedef long double ld;
    typedef unsigned long long ull;
    const int M = 5e5 + 10;
    const int mod = 1e9+7;
    const double eps = 1e-7;
    
    # define RG register
    # define ST static
    
    
    namespace FIFO {
        char ch,B[1<<20],*S=B,*T=B;
        #define getc() (S==T&&(T=(S=B)+fread(B,1,1<<20,stdin),S==T)?0:*S++)
        #define isd(c) (c>='0'&&c<='9')
        int aa,bb;int F(){
            while(ch=getc(),!isd(ch)&&ch!='-');ch=='-'?aa=bb=0:(aa=ch-'0',bb=1);
            while(ch=getc(),isd(ch))aa=aa*10+ch-'0';return bb?aa:-aa;
        }
    }
    #define gi FIFO::F()
    #define BUFSIZE 5000000
    namespace fob {char b[BUFSIZE]={},*f=b,*g=b+BUFSIZE-2;}
    #define pob (fwrite(fob::b,sizeof(char),fob::f-fob::b,stdout),fob::f=fob::b,0)
    #define pc(x) (*(fob::f++)=(x),(fob::f==fob::g)?pob:0)
    struct foce {~foce() {pob; fflush(stdout);}} _foce;
    namespace ib {char b[100];}
    inline void pint(int x)
    {
        if(x==0) {pc(48); return;}
        //if(x<0) {pc('-'); x=-x;} //如果有负数就加上 
        char *s=ib::b;
        while(x) *(++s)=x%10, x/=10;
        while(s!=ib::b) pc((*(s--))+48);
    }
    
    int n, L, U, tot, rtn;
    const double mINF = -1e18;
    
    ST int head[M], nxt[M], to[M], w[M], rt[M];
    inline void add(int u, int v, int _w) {
        ++tot; nxt[tot] = head[u]; head[u] = tot;
        to[tot] = v; w[tot] = _w;
    }
    inline void adde(int u, int v, int _w) {
        add(u, v, _w), add(v, u, _w);
    }
    
    struct pa {
        int a, b;
        pa() {}
        pa(int a, int b) : a(a), b(b) {}
    };
    
    namespace DFZ {
        bool ok;
        double SUB;
        ST bool vis[M];
        ST int sz[M], mx[M];
        int mi, centre;
        
        void dfsSize(int x, int fa=0) {
            sz[x] = 1; mx[x] = 0;
            for (RG int i=head[x]; i; i=nxt[i]) {
                if(to[i] == fa || vis[to[i]]) continue;
                dfsSize(to[i], x);
                sz[x] += sz[to[i]];
                if(sz[to[i]] > mx[x]) mx[x] = sz[to[i]];
            }
        }
        
        void dfsCentre(int x, int tp, int fa=0) {
            if(sz[tp] - sz[x] > mx[x]) mx[x] = sz[tp] - sz[x];
            if(mx[x] < mi) mi = mx[x], centre = x;
            for (RG int i=head[x]; i; i=nxt[i]) {
                if(to[i] == fa || vis[to[i]]) continue;
                dfsCentre(to[i], tp, x);
            }
        }
        
        inline int getdep(int x, int fa=0) {
            int ret = 0;
            for (RG int i=head[x], t; i; i=nxt[i]) {
                if(to[i] == fa || vis[to[i]]) continue;
                if((t = getdep(to[i], x)) > ret) ret = t;
            }
            return ret + 1;
        }
        
        ST int q[M];
        ST double f[M], g[M];
        int fn, gn;
        void getAns(int x, int fa, double ww, int d) {
            if(d > U) return ;
            if(d > gn) gn = d;
            if(ww > g[d]) g[d] = ww;
            for (RG int i=head[x]; i; i=nxt[i]) {
                if(to[i] == fa || vis[to[i]]) continue;
                getAns(to[i], x, ww+w[i]-SUB, d+1);
            }
        }          
        
        vector< pa > son[M];
        inline void calc(int x) {
    //        cout << "x=" << x << endl;
            RG int mxdep = 0, dep;
            fn = 0; f[0] = 0;
            for (RG int i=head[x]; i; i=nxt[i]) {
                if(vis[to[i]]) continue;
                dep = getdep(to[i], x);
                son[dep].push_back(pa(to[i], w[i]));
                if(dep > mxdep) mxdep = dep;
            }
            for (RG int i=0; i<=mxdep; ++i) {
                if(!ok)
                    for (RG int p=0; p<son[i].size(); ++p) {
                        int y = son[i][p].a;// cout << y << endl;
                        gn = 0; g[0] = 0;
                        getAns(y, x, son[i][p].b-SUB, 1);
                        RG int b = gn, head = 1, tail = 0;
                        for (RG int a=0; a<=fn; ++a) {
                            while(b >= 0 && a+b >= L) {
                                while(head <= tail && a+q[head] > U) ++head;
                                while(head <= tail && g[q[tail]] < g[b]) --tail;
                                q[++tail] = b; --b;
                            }
                            if(head <= tail && g[q[head]] + f[a] > -eps) {
                                ok = 1;                    
                                for (int j=0; j<=fn; ++j) f[j] = mINF;
                                for (int j=0; j<=gn; ++j) g[j] = mINF;
                                goto here;
                            }
                        }
                        if(fn < gn) fn = gn;
                        for (RG int j=0; j<=gn; ++j) if(f[j] < g[j]) f[j] = g[j];
                        for (RG int j=0; j<=gn; ++j) g[j] = mINF;
                    }
                here:;
                son[i].clear();
            }
            for (RG int j=0; j<=fn; ++j) f[j] = mINF;
            vis[x] = 1;    
        }
        
        void dfs(int x) {
            dfsSize(x); mi = n;
            dfsCentre(x, x);
            x = centre;
            rt[++rtn] = x;
            vis[x] = 1;
            for (RG int i=head[x]; i; i=nxt[i])
                if(!vis[to[i]]) dfs(to[i]);    
        }
        
        inline bool main(double x) {
            SUB = x; ok = 0;
            for (RG int i=1; i<=n; ++i) vis[i] = 0;
            for (int i=1; i<=rtn; ++i) {
                calc(rt[i]);
                if(ok) return 1;
            }
            return 0;
        }
    }
    
    int main() {
    //    freopen("bzoj1758.in", "r", stdin);
        double l = 0.0, r = -1e9, mid;
        n = gi; L = gi; U = gi;
    //    cin >> n >> L >> U;
        for (RG int i=1, u, v, _w; i<n; ++i) {
            u = gi; v = gi;_w = gi;
    //        scanf("%d%d%d", &u, &v, &_w);
            adde(u, v, _w);
            if(_w > r) r = _w;
        }
        
        for (RG int i=1; i<=n; ++i) DFZ::vis[i] = 0;
        DFZ::dfs(1);
        for (RG int i=0; i<=n; ++i) DFZ::f[i] = DFZ::g[i] = mINF;
    
        while(r-l > 1e-4) {
            mid = (l+r)/2.0;
            if(DFZ::main(mid)) l = mid;
            else r = mid;
        }
        
        printf("%.3lf
    ", l);
        
        return 0;
    }
    View Code
  • 相关阅读:
    提单管理
    SAP Using Text Modules in Adobe Forms
    创建设备任务清单
    HR常用事务代码
    SAP 如何查看用户登录信息
    abap常用函数
    CK13物料价格评估的数据ALV显示
    常用事务代码
    计算物料制造成本估算,比较重要的表
    IT_sort用法实例
  • 原文地址:https://www.cnblogs.com/galaxies/p/bzoj1758.html
Copyright © 2020-2023  润新知