• Test 3.27 T1 立方体大作战


    Description

    ​ 一个叫做立方体大作战的游戏风靡整个 Byteotia。这个游戏的规则是相当复杂的,所以我们只介绍他的简单规则:给定玩家一个有 2n 个元素的栈,元素一个叠一个地放置。这些元素拥有 n 个不同的编号,每个编号正好有两个元素。玩家每次可以交换两个相邻的元素。如果在交换之后,两个相邻的元素编号相同.则将他们都从栈中移除,所有在他们上面的元素都会掉落下来并且可以导致连锁反应。玩家的目标是用最少的步数将方块全部消除。

    Input

    输入文件第一行包含一个正整数 n(1<=n<=50000)。接下来 2n 行每行一个数ai,从上到下描述整个栈,保证每个数出现且仅只出现两次(1<=ai<=n)。初始时,没有两个相同元素相邻。并且保证所有数据都能在 1000000 步以内出解。

    Output

    输出文件第一行包含一个数 m,表示最少的步数。

    Sample Input #1

    5

    5

    2

    3

    1

    4

    1

    4

    3

    5

    2

    Sample Output #1

    2

    Sample Input #2

    3

    1

    2

    3

    1

    2

    3

    Sample Output

    3

    Solution

    假设要消去第i个和第j个方块,那么当这两个方块消去时,只会影响有一个元素在区(i,j)中的两个元素的距离。那么我们需要以一种方式去消去这些方块。在决定两种方块的消去顺序时,假设其对应区间为包含关系,那么显然先消去被包含的区间要更优。若两个区间仅存在交集,那么无论先消去哪两个都一样。如果两个区间的交集为空,那么消去顺序对答案没有影响。综上所述,我们得到如下贪心策略:每当遇到一个重复出现的元素时就消去它。每次消去的操作次数即为区间中还没有消去的元素个数,可以转化为区间和用树状数组维护。如果一个点上有元素就设为1,消去后变为0。

    #include <iostream>
    #include <cstdio>
    #define N 50002
    using namespace std;
    int n,i,pos[N],c[N],ans;
    int lowbit(int x)
    {
    	return x&(-x);
    }
    void modify(int x,int y)
    {
    	for(int i=x;i<=2*n;i+=lowbit(i)) c[i]+=y;
    }
    int sum(int x)
    {
    	int ans=0;
    	for(int i=x;i>=1;i-=lowbit(i)) ans+=c[i];
    	return ans;
    }
    int main()
    {
    	freopen("tet.in","r",stdin);
    	freopen("tet.out","w",stdout);
    	cin>>n;
    	for(i=1;i<=2*n;i++){
    		int x;
    		cin>>x;
    		if(pos[x]==0){
    			pos[x]=i;
    			modify(i,1);
    		}
    		else{
    			ans+=sum(i)-sum(pos[x]);
    			modify(pos[x],-1);
    		}
    	}
    	cout<<ans<<endl;
    	fclose(stdin);
    	fclose(stdout);
    	return 0;
    }
    
    
  • 相关阅读:
    CheckBox单选功能
    DOTNET
    常用命令行
    不能调试的问题的解决
    url字符串中含有中文的处理
    案例:星移eWorkflow.net系统
    使用正则表达式求完整路径中的文件名
    缺少一个***.resource的报告的解决
    Mapx中的图元移动
    Distance计算的距离随经纬度不同
  • 原文地址:https://www.cnblogs.com/LSlzf/p/10632380.html
Copyright © 2020-2023  润新知