codeforces 1208D Restore Permutation

本文介绍了解决 CodeForces 平台上的 1208D 题目的方法。该题目可通过逆向思维,从后往前计算每个元素的值,使用树状数组维护已确定数字的前缀和,从而高效求解。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

传送门:http://codeforces.com/problemset/problem/1208/D

大水题= =,比C的构造不知道水到哪里去了

从后往前考虑,最后一个s[n]一定就是比a[n]小的所有数字的和,所以可以直接算出a[n]。

接下来,s[n-1]是去掉a[n]之后的情况下,比a[n-1]小的所有数字的和,我们也可以知道a[n-1]的值

这样用一个树状数组维护一下去掉后面已经确定的数字,当前情况下的前缀和即可

#include<bits/stdc++.h>
#define maxl 200010
using namespace std;

int n;
long long a[maxl],s[maxl]; 
long long b[maxl];

inline void add(int i,int x)
{
	while(i<=n)
	{
		b[i]+=x;
		i+=i&-i;
	}
}

inline void prework()
{
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
		scanf("%lld",&s[i]);
	for(int i=1;i<=n;i++)
		add(i,i);
}

inline long long find(long long mid)
{
	long long sum=0,ret=0;
	int up=log2(n),d=1<<up;
	for(int i=up;i>=0;i--)
	{
		if(sum+b[ret+d]<=mid && ret+d<n)
		{
			sum+=b[ret+d];
			ret+=d;
		}
		d=d>>1;
	}
	return ret+1;
}

inline void mainwork()
{
	long long sum=0;
	for(int i=n;i>=1;i--)
	{
		a[i]=find(s[i]);
		add(a[i],-a[i]);
	}
}

inline void print()
{
	for(int i=1;i<=n;i++)
		printf("%lld ",a[i]);
}

int main()
{
	prework();
	mainwork();
	print();
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值