zoukankan      html  css  js  c++  java
  • 【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;
    }
    


  • 相关阅读:
    #3232. 「POI2019 R1」Najmniejsza wspólna wielokrotność
    bzoj4129 Haruna's Breakfast
    uoj:【UNR #3】配对树
    #3409. 小P的生成树(mst)
    #1790. 小A的树
    #2689. 异或树(tree)
    #4740. 校运会
    #4738. 迷惑数字统计
    #4742. 寻找字符串
    dtoj1825. 放棋子(chess)
  • 原文地址:https://www.cnblogs.com/Maxwei-wzj/p/9793987.html
Copyright © 2011-2022 走看看