【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
",ans);
  }
  
  return 0;
}


原文地址:https://www.cnblogs.com/Maxwei-wzj/p/9793986.html