Codeforces 1208D Restore Permutation

Posted qingjiuling

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Codeforces 1208D Restore Permutation相关的知识,希望对你有一定的参考价值。

题目链接:https://www.luogu.org/problem/CF1208D

题意:现在有一个从11到nn的一个全排列,但是你不知道这个排列到底是什么,但是你有一个sum[i],sum[i]的值是所有满足j<i并且a[j]<a[i]的值之和,给出每个点的sum[i],求出原本的全排列

分析:我们从最后一个点n开始看,sum[n]肯定表示的是一段连续的都比a[n]小的的从1到j的数的和,根据这个和我们可以找出a[n]

而sum[n-1]表示的是一段连续的都比a[n-1]小的的从1到k的数的和(这里注意,如果本身a[n]也比a[n-1]小的话,这个和里是不包含a[n]的,也就是说事实上此时的sum[n-1]表示的是[1,a[n]),(a[n],k)的和

那么思路就出来了,我们可以从后往前一个个确定,确定了一个数之后就把那个数赋为0 ,之后找和的时候就不会遇到那个数了

也就是说会用单单点修改,和查询时哪个区间的和 线段树即可

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int inf=1e18;
const int maxn=2e5+7; 
const int mod=1e9+7;
#define mem0(a) memset(a,0,sizeof(a))
#define meminf(a) memset(a,0x3f,sizeof(a))
#define ls rt<<1
#define rs rt<<1|1
ll a[maxn],ans[maxn];
ll dat[maxn<<2];
void add(int rt,int l,int r,int x,int y)
    if(l==r)
        dat[rt]+=y;
        return ;
    
    ll mid=(l+r)>>1;
    if(x<=mid)add(ls,l,mid,x,y);
    else add(rs,mid+1,r,x,y);
    dat[rt]=dat[ls]+dat[rs];

ll query(int rt,int l,int r,ll v)
    if(l==r)
        return l;
    
    ll mid=(l+r)>>1;
    if(dat[ls]>v)return query(ls,l,mid,v);
    else return query(rs,mid+1,r,v-dat[ls]);

int main()
    int n;scanf("%d",&n);
    for(int i=1;i<=n;i++)
        scanf("%I64d",&a[i]);
        add(1,1,n,i,i);
    
    for(int i=n;i>0;i--)
        ans[i]=query(1,1,n,a[i]);
        add(1,1,n,ans[i],-ans[i]);
        //将第i个数赋为0,之后就不会加了 
    
    for(int i=1;i<n;i++)printf("%I64d ",ans[i]);
    printf("%I64d\n",ans[n]); 
    return 0;

 

以上是关于Codeforces 1208D Restore Permutation的主要内容,如果未能解决你的问题,请参考以下文章

CodeForces1208D

[codeforces]#350F. Restore a Number

CodeForces 670F Restore a Number

CodeForces 404C Restore Graph (构造)

codeforces1028E: Restore Array

Codeforces Round #237 (Div. 2) / 404C Restore Graph (构造最短路径树)