POJ 2299 && HDU 3743 离散化+线段树

给出一个长度为n的数列,你每一次可以随意交换其中两个数字的位置。问你至少交换几次,才能使得这个数列是个单调递增数列。

最多50W个数据  离散化 存到线段树中

单点更新 成段查找即可

#include "iostream"
#include "algorithm"
using namespace std;
struct node
{
	int x,id;
} num[501000];

int a[501000];

struct comp
{
	int l,r;
	__int64 sum;
} data[1200001];

bool cmp(const node a,const node b)
{
	return a.x<b.x;
}

void build(int l,int r,int k)
{
	int mid;
	data[k].l=l;
	data[k].r=r;
	data[k].sum=0;

	if (l==r) return ;

	mid=(l+r)/2;
	build(l,mid,k*2);
	build(mid+1,r,k*2+1);

	return ;
}

__int64 search(int l,int r,int k)
{
	int mid;
	if (data[k].l==l && data[k].r==r)
		return data[k].sum;



	mid=(data[k].l+data[k].r)/2;

	if (r<=mid) return search(l,r,k*2);
	else 
		if (l>mid) return search(l,r,k*2+1);
		else 
			return search(l,mid,k*2)+search(mid+1,r,k*2+1);
}

void updata(int n,int k)
{
	int mid;
	if (data[k].l==n && data[k].r==n)
	{
		data[k].sum=1;
		return ;
	}

	mid=(data[k].l+data[k].r)/2;
	if (n<=mid) updata(n,k*2);
	else  updata(n,k*2+1);

	data[k].sum=data[k*2].sum+data[k*2+1].sum;
}


int main()
{
	int n,i,k;
	__int64 ans;
	while (scanf("%d",&n)!=EOF)
	{
		if (n==0) break;

		for (i=0;i<n;i++)
		{
			scanf("%d",&num[i].x);
			num[i].id=i;
		}

		sort(num,num+n,cmp);

		k=0;
		for (i=0;i<n;i++)
			a[num[i].id]=k++;

		build(0,n-1,1);

		ans=0;

		for (i=0;i<n;i++)
		{
			ans+=search(a[i],n-1,1);
			updata(a[i],1);
		}
		printf("%I64d\n",ans);
	}
	return 0;
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值