ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

UOJ621 【JOISC2021】最差记者 4

2021-05-01 19:34:16  阅读:164  来源: 互联网

标签:rt int 最差 mn JOISC2021 tag 权值 UOJ621 define


UOJ621 【JOISC2021】最差记者 4

线段树合并

从早上研究到晚上,终于干掉了这道题

对于题目中rating关系建图。

首先,每个点的出度为\(1\),因此整张图是由多个基环内向树组成的,我们需要对于每个基环内向树计算答案,相加即可。

容易发现,在一棵基环内向树上,环上点的权值必然相等。

我们先考虑树的情况,需要满足子节点的权值\(\ge\)父节点的权值,可以发现最优方案中,父节点的权值一定是保持自己的权值不变,或者取子节点中的最小权值。然后再考虑叶子节点,显然它的权值要么保持不变,要么取\(INF=10^9\)。

因此在一棵大小为\(n\)的基环内向树中,节点权值取值范围最多只有\(n+1\)个数。我们可以进行\(dp\),维护一个子树的根节点权值等于任意在其子树内节点权值(或\(INF\))时的最小代价。考虑到从子节点推到父节点,比如两棵根节点权值分别为\(s,t(s<t)\)的子树,最终我们会将他们俩组成的答案合并到\(s\)中,这个可以在线段树合并的过程中实现。最终,对于一棵树,我们可以取出根节点的权值等于任意在其子树内的节点权值(或\(INF\))情况下的最小代价。

因此,对于一棵基环内向树,我们先处理每棵子树,然后直接枚举每个权值来计算答案。对于枚举的权值\(V\)来说,每棵子树根节点的权值必须\(\ge V\),我们可以默认根节点权值必须更改,然后对于那些根节点权值不更改的进行特判。

我们优化这一过程,从大到小枚举权值,然后对于每棵子树,不断拓展它的取值范围,这可以用优先队列进行动态维护。同样,对根节点权值不更改的情况进行特判。

然后我们就解决了这道题。

时间复杂度:\(O(n \log n)\)。

\(Code:\)

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<vector>
#include<queue>
#include<map>
#define N 200005
#define M 10000005
#define ll long long
#define pr pair<int,ll>
#define mp make_pair
#define IT vector<int> :: iterator
#define pIT vector< pr > :: iterator
#define mIT map<int,bool> :: iterator
using namespace std;
const ll INF=1919191919191919;
int n,cc,a[N],h[N],c[N],d[N],rd[N],rt[N];
vector<int>e[N],val[N];
vector< pr >co[N];
queue<int>q;
map<int,bool>ht;
int z0,z[N];
bool vis[N];
int cnt,n1,n2;
ll ans,sz[N],g[N];
#define ls(p) tr[p].ch[0]
#define rs(p) tr[p].ch[1]
#define mn(p) tr[p].Mn
#define tag(p) tr[p].Tag
struct node
{
    int ch[2];
    ll Mn,Tag;
}tr[M];
void push_tag(int p,ll z)
{
    if (!p)
        return;
    mn(p)+=z,tag(p)+=z;
    mn(p)=min(mn(p),INF),tag(p)=min(tag(p),INF);
}
void push_down(int p)
{
    if (tag(p))
    {
        push_tag(ls(p),tag(p));
        push_tag(rs(p),tag(p));
        tag(p)=0;
    }
}
void update(int p)
{
    mn(p)=min(mn(ls(p)),mn(rs(p)));
}
void modify(int &p,int l,int r,int x,int y)
{
    if (!p)
        p=++cnt;
    if (l==r)
    {
        mn(p)+=y;
        return;
    }
    push_down(p);
    int mid(l+r >> 1);
    if (x<=mid)
        modify(ls(p),l,mid,x,y); else
        modify(rs(p),mid+1,r,x,y);
    update(p);
}
void modify2(int &p,int l,int r,int x,ll y)
{
    if (!p)
        p=++cnt;
    if (l==r)
    {
        mn(p)=y;
        return;
    }
    push_down(p);
    int mid(l+r >> 1);
    if (x<=mid)
        modify2(ls(p),l,mid,x,y); else
        modify2(rs(p),mid+1,r,x,y);
    update(p);
}
int combine(int x,int y,int l,int r,ll xm,ll ym)
{
    if (!x && y)
        push_tag(y,xm);
    if (x && !y)
        push_tag(x,ym);
    if (!x || !y)
        return x|y;
    if (l==r)
    {
        mn(x)=min(mn(x)+min(ym,mn(y)),mn(y)+min(xm,mn(x)));
        return x;
    }
    push_down(x),push_down(y);
    int mid(l+r >> 1);
    ls(x)=combine(ls(x),ls(y),l,mid,min(xm,mn(rs(x))),min(ym,mn(rs(y))));
    rs(x)=combine(rs(x),rs(y),mid+1,r,xm,ym);
    update(x);
    return x;
}
ll calc(int p,int l,int r,int x,int y)
{
    if (!p)
        return INF;
    if (l==x && r==y)
        return mn(p);
    push_down(p);
    int mid(l+r >> 1);
    if (y<=mid)
        return calc(ls(p),l,mid,x,y); else
    if (x>mid)
        return calc(rs(p),mid+1,r,x,y); else
        return min(calc(ls(p),l,mid,x,mid),calc(rs(p),mid+1,r,mid+1,y));
}
void dfs(int p,int l,int r,int u)
{
    if (!p)
        return;
    if (l==r)
    {
        co[u].push_back(mp(l,mn(p)));
        return;
    }
    push_down(p);
    int mid(l+r >> 1);
    dfs(ls(p),l,mid,u),dfs(rs(p),mid+1,r,u);
}
void dfs(int u)
{
    ht[h[u]]=true;
    vis[u]=true;
    sz[u]=c[u];
    int ct(0);
    for (IT it=e[u].begin();it!=e[u].end();++it)
    {
        int v(*it);
        if (v==n1 || v==n2)
            continue;
        ++ct;
    }
    if (!ct)
    {
        modify(rt[u],1,cc,h[u],0);
        modify(rt[u],1,cc,cc,c[u]);
    } else
    {
        for (IT it=e[u].begin();it!=e[u].end();++it)
        {
            int v(*it);
            if (v==n1 || v==n2)
                continue;
            dfs(v);
            sz[u]+=sz[v];
            if (!rt[u])
                rt[u]=rt[v]; else
                rt[u]=combine(rt[u],rt[v],1,cc,INF,INF);
        }
        ll zt(calc(rt[u],1,cc,h[u],cc));
        push_tag(rt[u],c[u]);
        modify2(rt[u],1,cc,h[u],zt);
    }
}
struct node2
{
    pIT it;
    int id;
    node2 () {}
    node2 (pIT It,int Id):it(It),id(Id) {}
    bool operator < (const node2 &A) const
    {
        return it->first<A.it->first;
    }
};
int main()
{
    scanf("%d",&n);
    for (int i=1;i<=n;++i)
        scanf("%d%d%d",&a[i],&h[i],&c[i]),e[a[i]].push_back(i),++rd[a[i]],d[i]=h[i];
    sort(d+1,d+n+1);
    cc=unique(d+1,d+n+1)-d-1;
    for (int i=1;i<=n;++i)
        h[i]=lower_bound(d+1,d+cc+1,h[i])-d;
    ++cc;
    for (int i=1;i<=n;++i)
        if (!rd[i])
            q.push(i);
    while (!q.empty())
    {
        int u(q.front());
        vis[u]=true;
        q.pop();
        --rd[a[u]];
        if (!rd[a[u]])
            q.push(a[u]);
    }
    mn(0)=INF;
    for (int i=1;i<=n;++i)
        if (!vis[i])
        {
            z0=0;
            z[++z0]=i;
            for (int j=a[i];j!=i;j=a[j])
                z[++z0]=j;
            ll oc(0);
            priority_queue<node2>Q;
            for (int j=1;j<=z0;++j)
            {
                n1=(j==1)?z[z0]:z[j-1];
                n2=(j==z0)?z[1]:z[j+1];
                dfs(z[j]);
                modify(rt[z[j]],1,cc,h[z[j]],c[z[j]]);
                dfs(rt[z[j]],1,cc,j);
                val[h[z[j]]].push_back(j);
                g[j]=sz[z[j]];
                oc+=g[j];
                pIT it=co[j].end();
                --it;
                Q.push(node2(it,j));
            }
            ht[cc]=true;
            ll tas(INF);
            mIT mt=ht.end();
            --mt;
            for (;;--mt)
            {
                int x(mt->first);
                while (!Q.empty() && (Q.top().it->first)>=x)
                {
                    int u(Q.top().id);
                    pIT it(Q.top().it);
                    Q.pop();
                    oc-=g[u];
                    g[u]=min(g[u],it->second);
                    oc+=g[u];
                    if (it!=co[u].begin())
                        --it,Q.push(node2(it,u));
                }
                tas=min(tas,oc);
                ll kt(oc);
                for (IT it=val[x].begin();it!=val[x].end();++it)
                {
                    int u(*it);
                    ll vt(calc(rt[z[u]],1,cc,x,x));
                    kt+=min(0LL,vt-c[z[u]]-g[u]);
                }
                val[x].clear();
                tas=min(tas,kt);
                if (mt==ht.begin())
                    break;
            }
            ans+=tas;
            for (int j=1;j<=z0;++j)
                co[j].clear();
            ht.clear();
        }
    printf("%lld\n",ans);
    return 0;
}

标签:rt,int,最差,mn,JOISC2021,tag,权值,UOJ621,define
来源: https://www.cnblogs.com/GK0328/p/14724613.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有