zoukankan      html  css  js  c++  java
  • UOJ418. 【集训队作业2018】三角形

    http://uoj.ac/problem/418

    题解

    考虑激活每个节点时,它的每个儿子都是放满的。

    那每一次的操作我们可以用一个二元组来表示((w_i-sum w_{son},sum w_{son}))

    表示这一次操作完后的增量和这次操作中石子数达到的峰值。

    那么一个节点被操作当且仅当它的所有儿子都被操作。

    这样很不好处理,所以我们把整个操作序列倒过来,这样限制一个点的只有他的父亲。

    那么二元组会变成:((sum w_{son}-w_i,sum w_{son})),我们还是需要最小化这个序列的历史最值,因为按照这个序列模拟的话是可以还原出它的每一个时刻的。

    然后考虑贪心,我们需要对每一个操作求出它的优先度。

    对于(x<0)的操作,它显然放在前面会更优,如果有多个(<0)的操作,(y)更小的放在前面。

    对于(xgeq 0)的操作,我们要让(x,y)优于(dx,dy),那么就有:

    [max(y,dy+x)<max(dy,dx+y) ]

    前面的常量先不管。

    [dy+x<dx+y ->x-y>dx-dy ]

    于是我们弄清楚了每个元素的优先度,然后我们求出全局的一个最优序列。

    每次找到最优的,如果这个点还没有被父亲激活,那么就和父亲合并。

    通过观察我们发现每棵子树的最优序列是全局的子序列,然后我们可以线段树合并求答案。

    代码

    #include<bits/stdc++.h>
    #define N 200002
    #define ls tr[cnt].l
    #define rs tr[cnt].r
    using namespace std;
    typedef long long ll;
    int f[N],n,id[N],fa[N],T[N],tott,nxt[N];
    bool vis[N];
    ll w[N],s[N],ans[N],val[N];
    inline ll rd(){
        ll x=0;char c=getchar();bool f=0;
        while(!isdigit(c)){if(c=='-')f=1;c=getchar();}
        while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
        return f?-x:x;
    }
    vector<int>vec[N];
    int find(int x){return f[x]=f[x]==x?x:find(f[x]);}
    struct node{
        ll x,y;
        int h,t;
        inline node operator +(const node &b)const{return node{x+b.x,max(y,x+b.y),h,b.t};}
        inline bool operator <(const node &b)const{
            int o1=x>=0,o2=b.x>=0;
            if(o1!=o2)return x<b.x;
            if(!o1){
                if(y!=b.y)return y<b.y;
                return h<b.h;
            }
            if(y-x!=b.y-b.x)return y-x>b.y-b.x;
            return h<b.h;
        }
    };
    struct seg{
        node x;
        int l,r;
    }tr[N*23];
    node pre[N];
    set<node>q;
    int merge(int u,int v){
        if(!u||!v)return u|v;
        tr[u].l=merge(tr[u].l,tr[v].l);
        tr[u].r=merge(tr[u].r,tr[v].r);
        tr[u].x=tr[tr[u].l].x+tr[tr[u].r].x;
        return u;
    }
    void ins(int &cnt,int l,int r,int x,int id){
        cnt=++tott;
        if(l==r){
          tr[cnt].x=node{val[id],s[id],l,l};
          return;
        }
        int mid=(l+r)>>1;
        if(x<=mid)ins(ls,l,mid,x,id);
        else ins(rs,mid+1,r,x,id);
        tr[cnt].x=tr[ls].x+tr[rs].x;
    }
    void dfs(int u,int fa){
        ins(T[u],1,n,id[u],u);
        for(vector<int>::iterator it=vec[u].begin();it!=vec[u].end();++it){
            int v=*it;
            dfs(v,u);
            T[u]=merge(T[u],T[v]);
        }
        ans[u]=tr[T[u]].x.y+w[u];
    }
    int main(){
        int TT=rd();
        n=rd();
        for(int i=2;i<=n;++i)fa[i]=rd(),vec[fa[i]].push_back(i);
        for(int i=1;i<=n;++i)w[i]=rd(),s[fa[i]]+=w[i],f[i]=i;
        for(int i=1;i<=n;++i){
            val[i]=s[i]-w[i];
            pre[i]=node{val[i],s[i],i,i};
            q.insert(pre[i]);
        }
        vis[0]=1;
        int now=0;
        while(!q.empty()){
            set<node>::iterator it=q.begin();
            node x=*it;
            q.erase(it);
            if(vis[fa[x.h]]){
                nxt[now]=x.h;
                while(now!=x.t)vis[now]=1,now=nxt[now];
                vis[now]=1;
            }
            else{
                int pr=find(fa[x.h]);
                q.erase(pre[pr]);
                nxt[pre[pr].t]=pre[x.h].h;
                pre[pr]=pre[pr]+pre[x.h];
                f[find(x.h)]=pr;
                q.insert(pre[pr]);
            }
        }
        int cnt=0;
        now=0;
        for(int i=1;i<=n;++i){
            cnt++;
            now=nxt[now];
            id[now]=i;
        }
        dfs(1,0);
        for(int i=1;i<=n;++i)printf("%lld ",ans[i]);
        return 0;
    }
    
  • 相关阅读:
    51nod 1380 夹克老爷的逢三抽一 堆 脑洞题
    洛谷P2168 荷马史诗 堆 哈夫曼树
    HDU 4343 Interval query 倍增思想, DP
    洛谷P1969 积木大赛 贪心 差分
    codves1052 地鼠游戏 贪心
    hdu6031 Innumerable Ancestors
    Codeforces 278C Learning Languages(并查集) 求连通块
    [LeetCode]80. Remove Duplicates from Sorted Array II删除数组中的重复值
    [LeetCode]86. Partition List分离链表
    [LeetCode]42. Trapping Rain Water雨水填坑
  • 原文地址:https://www.cnblogs.com/ZH-comld/p/11000039.html
Copyright © 2011-2022 走看看