zoukankan      html  css  js  c++  java
  • CF1119F Niyaz and Small Degrees

    CF1119F Niyaz and Small Degrees

    另类复杂度分析题

    对于给定的d

    f[x][0/1]x为根的子树,到父亲的边连不连,整个子树的花费最小值

    转移时候,设要删掉k的出边,都先变成∑f[son][1],再把f[son][0]+vf[son]-f[son][1]插入堆中,取最小的k个

    当f[son][0]+vf[son]-f[son][1]<0一定选择,先选上,令k--

    所有的d

    对于du[x]<=d的x,其度数最后是多少都满足,所以可以不用管了。删除这个点和出边

    对剩下的点的连通块进行上述dp

    很麻烦的事情:

    1.du[x]<=d的x删除了,但是其实还要考虑是否会删除

    所以把x的所有出边(y,val)的y的堆里面加入val,设这些边为特殊边

    2.处理的时候,把会访问儿子的f[son][0]+vf[son]-f[son][1]也加入堆中,

    设需要删除k条边

    把堆的限制卡成k。然后堆内元素的和就是前k小的值

    但是需要还原,所以这个时候删除的东西再用vector存,然后还原,把访问的儿子的f[son][0]+vf[son]-f[son][1]再删除

    所以,堆需要懒惰删除+查询总和

    堆是大根堆

    (或者手写平衡树查前k小?)

    3.如果用堆

    那么对于特殊边,也要先卡成k,这些扔掉的特殊边就不用了(因为k单调)

    这样,每次求dp时候暴力卡成k复杂度就是对的。

    否则菊花图就完了。

    每个点会被访问du[x]次,总复杂度O(nlogn)

    #include<bits/stdc++.h>
    #define reg register int
    #define il inline
    #define fi first
    #define se second
    #define mk(a,b) make_pair(a,b)
    #define numb (ch^'0')
    #define pb push_back
    #define solid const auto &
    #define enter cout<<endl
    #define pii pair<int,int>
    using namespace std;
    typedef long long ll;
    template<class T>il void rd(T &x){
        char ch;x=0;bool fl=false;
        while(!isdigit(ch=getchar()))(ch=='-')&&(fl=true);
        for(x=numb;isdigit(ch=getchar());x=x*10+numb);
        (fl==true)&&(x=-x);
    }
    template<class T>il void output(T x){if(x/10)output(x/10);putchar(x%10+'0');}
    template<class T>il void ot(T x){if(x<0) putchar('-'),x=-x;output(x);putchar(' ');}
    template<class T>il void prt(T a[],int st,int nd){for(reg i=st;i<=nd;++i) ot(a[i]);putchar('
    ');}
    
    namespace Miracle{
    const int N=250000+5;
    int n;
    int du[N],rk[N];
    bool cmp1(int x,int y){
        return du[x]<du[y];
    }
    bool cmp2(int x,int y){
        return du[x]>du[y];
    }
    struct node{
        int to;ll val;
        node(){}
        node(int x,ll v){
            to=x;val=v;
        }
        bool friend operator <(node a,node b){
            return du[a.to]>du[b.to];
        }
    };
    vector<node>to[N];
    int sta[N],top;
    bool vis[N];
    ll f[N][2];
    struct Heap{
        priority_queue<ll>q,d;
        int sz;
        ll sum;
        void dele(ll v){
            d.push(v);--sz;sum-=v;
        }
        void ins(ll v){
            q.push(v);++sz;sum+=v;
        }
        ll top(){
            while(q.size()&&d.size()&&q.top()==d.top()) q.pop(),d.pop();
            if(q.size()) return q.top();
            return -2333;
        }
        void pop(){
            while(q.size()&&d.size()&&q.top()==d.top()) q.pop(),d.pop();
            if(q.size()){
                sum-=q.top();--sz;
                q.pop();
            }
        }
    }hp[N];
    int lim;
    void sol(int x){
    //    cout<<" sol "<<x<<endl;
        int m=max(0,(int)du[x]-lim);
        while(hp[x].sz>m) hp[x].pop();
        vis[x]=1;
        ll tot=0;
        vector<int>a,b;
        for(solid y:to[x]){
            if(vis[y.to]) continue;
            sol(y.to);
            if(f[y.to][0]+y.val-f[y.to][1]<0) --m,tot+=f[y.to][0]+y.val;
            else{
                tot+=f[y.to][1];
                hp[x].ins(f[y.to][0]+y.val-f[y.to][1]);
                b.push_back(f[y.to][0]+y.val-f[y.to][1]);
            }
        }
    //    cout<<" m1 "<<m<<" "<<tot<<" sz "<<hp[x].sz<<endl;
        m=max(m,0);
        while(hp[x].sz>m) {
            a.push_back(hp[x].top());
            hp[x].pop();
        }
    //    cout<<" end "<<hp[x].sum<<endl;
        f[x][1]=tot+hp[x].sum;
        --m;
        m=max(m,0);
        while(hp[x].sz>m){
            a.push_back(hp[x].top());
            hp[x].pop();
        }
        f[x][0]=tot+hp[x].sum;
        for(solid v:a) hp[x].ins(v);
        for(solid v:b) hp[x].dele(v);
    //    cout<<" tot "<<tot<<" m2 "<<m<<endl;
    //    cout<<" bac "<<f[x][0]<<" "<<f[x][1]<<endl;
    }
    int main(){
        rd(n);
        int x,y;ll v;
        for(reg i=1;i<n;++i){
            rd(x);rd(y);rd(v);
            to[x].push_back(node(y,v));
            to[y].push_back(node(x,v));
            ++du[x];++du[y];
        }
        
        for(reg i=1;i<=n;++i) {
            rk[i]=i;
            sort(to[i].begin(),to[i].end());
        }
        sort(rk+1,rk+n+1,cmp1);
        ll ans=0;
        int ptr=1;
        for(lim=0;lim<n;++lim){
            while(ptr<=n&&du[rk[ptr]]<=lim){
                int id=rk[ptr];
                vis[id]=1;
                for(solid y:to[id]){
                    hp[y.to].ins(y.val);
                    to[y.to].pop_back();
                }
                ++ptr;
            }
            ans=0;
            for(reg i=ptr;i<=n;++i){
                int id=rk[i];
                if(!vis[id]){
                    sol(id);
                    ans+=f[id][1];
                }
            }
            for(reg i=ptr;i<=n;++i) vis[rk[i]]=0;
            printf("%lld
    ",ans);
        }
        return 0;
    }
    
    }
    signed main(){
        Miracle::main();
        return 0;
    }
    
    /*
       Author: *Miracle*
    */
  • 相关阅读:
    UWP 应用获取各类系统、用户信息 (1)
    Windows Composition API 指南
    详解 UWP (通用 Windows 平台) 中的两种 HttpClient API
    Win2D 官方文章系列翻译
    Spring的IOC容器, AOP切面及启动流程简述
    maven和gradle的全局阿里云镜像代理
    SpringBoot项目中@Async方法没有执行的问题分析
    Oracle向MySQL迁移的注意点整理
    SpringBoot项目替换内部的依赖jar包
    MySQL的主从复制
  • 原文地址:https://www.cnblogs.com/Miracevin/p/10845258.html
Copyright © 2011-2022 走看看