【HOJ2430】Counting the Algorithms-区间维护

题目大意:有一个长度为2*N的数列,其中1~N的每个整数都出现2次,要将它们两两删除,删除一个元素以后,另一个元素也被消除,并获得等于它们位置标号之差的绝对值的分数,问删除完所有元素之后所能获得的最大分数是多少。

做法:可以发现,当一对元素被另一对元素包含时,先删除外面的一对元素是最优的;如果两对元素所表示的区间有一部分相交,那么先删哪一对结果都是一样的。所以,我们只需维护每对元素之间所剩的元素个数,从前往后删除即可。

以下是本人代码(树状数组):

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
int n,pos[100010]={0},a[200010]={0},c[200010]={0}; //pos[i]:值为i的一对元素的后面那个元素的位置
int ans;

int lowbit(int i)
{
  return i&(-i);
}

void add(int x,int a)
{
  for(int i=x;i<=2*n;i+=lowbit(i))
    c[i]+=a;
}

int sum(int x)
{
  int s=0;
  for(int i=x;i>0;i-=lowbit(i))
    s+=c[i];
  return s;
}

int main()
{
  while(scanf("%d",&n)!=EOF)
  {
    memset(c,0,sizeof(c));
	memset(pos,0,sizeof(pos));
    ans=0;
	for(int i=1;i<=2*n;i++)
	{
	  scanf("%d",&a[i]);
	  pos[a[i]]=i;
	  add(i,1);
	}
	for(int i=1;i<=2*n;i++)
	{
	  if (a[i])
	  {
	    ans+=sum(pos[a[i]])-sum(i);
	    add(i,-1);
	    add(pos[a[i]],-1);
		a[pos[a[i]]]=0;a[i]=0;
	  }
	}
	printf("%d\n",ans);
  }
  
  return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值