但战斗还未结束(war)

· · 个人记录

但战斗还未结束(war) 题解

0x01 解题思路

不难发现,题目给出的信息可以转化为 f_i 之间的大小关系,之后建图拓扑排序,i 在拓扑序中的位置显然即 f_i 的一种合法的值。

0x02 具体过程

0x03 代码实现

#include <bits/stdc++.h>
using namespace std;
const int N=5e5+5;
int a[N],b[N],f[N],mpos[N<<2],n,cnt=0;
bool vis[N];
int MAX(int x,int y){return b[x]>b[y]?x:y;}
void build(int p,int l,int r)
{
    if(l==r)return mpos[p]=l,void();
    int mid=(l+r)>>1;
    build(p<<1,l,mid);
    build(p<<1|1,mid+1,r);
    mpos[p]=MAX(mpos[p<<1],mpos[p<<1|1]);
    return;
}
void modify(int p,int l,int r,int x,int v)
{
    if(l==r)return b[x]=v,void();
    int mid=(l+r)>>1;
    if(x<=mid)modify(p<<1,l,mid,x,v);
    else modify(p<<1|1,mid+1,r,x,v);
    mpos[p]=MAX(mpos[p<<1],mpos[p<<1|1]);
    return;
}
int query(int p,int l,int r,int x,int y)
{
    if(x>r||y<l)return 0;
    if(x<=l&&r<=y)return mpos[p];
    int mid=(l+r)>>1;
    int resL=query(p<<1,l,mid,x,y);
    int resR=query(p<<1|1,mid+1,r,x,y);
    return MAX(resL,resR);
}
void dfs(int u)
{
    vis[u]=true;
    int to=b[u];
    modify(1,1,n,u,0);
    if(to<=n&&!vis[to])dfs(to);
    while(true)
    {
        int v=query(1,1,n,1,a[u]-1);
        if(b[v]<=u)break;
        dfs(v);
    }
    f[u]=++cnt;
    return;
}
int main()
{
    freopen("war.in","r",stdin);
    freopen("war.out","w",stdout);
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&a[i]);
        if(~a[i])b[a[i]]=i;
        else a[i]=n+1;
    }
    for(int i=1;i<=n;i++)if(!b[i])b[i]=n+1;
    build(1,1,n);
    for(int i=1;i<=n;i++)if(!vis[i])dfs(i);
    for(int i=1;i<=n;i++)printf("%d ",f[i]);
    return 0;
}