GDUT_专题五 J - Lost Cows

题目:

J - Lost Cows

题意:

有编号为1~n的n个数字乱序排序,对于每个位置的数字都知道在它之前有多少个数字比它小,求这个数字串。

分析:

初始化每一个叶子结点的值为1,对于正在查找的结点tree[p]对应的区间[l,r],如果每个数字都没有被选择过,并且该区间内未被选择的数字刚好比目前位置前面比它小的数字的数量多1,则可以直接选择rtree[p]=tree[p]-1,并进行标记。否则,如果该结点存在标记,就将标记向右结点传递并清除该标记,再向下查找。向如果其左结点tree[p*2]对应的区间内未被选择的数字-目前位置前面比它小的数字的数量\geq1,则向左结点查找;否则向右结点查找。

代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
long long n,m,a[1000010],tree[2000010],lazy[2000010];

void pushdown(long long p,long long l,long long r){
	tree[p*2+1]=tree[p*2+1]-lazy[p];
	lazy[p*2+1]=lazy[p*2+1]+lazy[p]; 
	lazy[p]=0;
}

void pushup(long long p){
	tree[p]=tree[p*2]+tree[p*2+1];
}

void built(long long p,long long l,long long r){
	lazy[p]=0;
	if (l==r){
		tree[p]=1;
		return;
	}
	long long mid=(l+r)/2;
	built(p*2,l,mid);
	built(p*2+1,mid+1,r);
	pushup(p); 
}

long long find(long long l,long long r,long long p,long long k){
	if (tree[p]==k && tree[p]==r-l+1){
		tree[p]--;
		lazy[p]++;
		return r;
	}
	pushdown(p,l,r);
	long long mid=(l+r)/2;
	long long x;
	if (k<=tree[p*2]) {
		x=find(l,mid,p*2,k);
	}
	else {
		x=find(mid+1,r,p*2+1,k-tree[p*2]);
	}
	pushup(p);
	return x;
}

int main()
{
	scanf("%lld",&n);
	a[1]=0;
	for (int i=2;i<=n;i++){
		scanf("%lld",&a[i]);
	}
	built(1,1,n);
	for (int i=n;i>=1;i--){
		a[i]=find(1,n,1,a[i]+1);
	}
	for (int i=1;i<=n;i++){
		printf("%lld\n",a[i]);
	}
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值