• 洛谷 P3460 [POI2007]TET-Tetris Attac


    [POI2007]TET-Tetris Attack

    题目描述

    一种名为 Tetris Attack 的猜谜游戏风靡 Byteotia。游戏本身非常复杂,因此我们只介绍它的简化规则:

    玩家拥有一个有 2 n 2n 2n 个元素的栈,一个元素放置在另一个元素上,这样一个组合有 n n n 个不同的符号标记。对于每个符号,栈中恰好有两个元素用一个符号标记。

    玩家可以交换两个相邻元素,即互换他们的位置。交换后,如果有两个相邻的元素标有相同的符号,则将他们都从栈中删除。然后,位于其上方的所有元素都会掉落下来,并且可以造成再次删除。

    玩家的目标是以最少的移动次数清空堆栈。请你编写一个程序,找出最少的移动次数及方案。

    输入格式

    第一行一个整数 n n n

    接下来的 2 n 2n 2n 行里给出了栈的初始内容,第 i + 1 i+1 i+1 行包含一个整数 a i a_i ai 1 ≤ a i ≤ n 1 \leq a_i \leq n 1ain),表示从底部数起第 i i i 个元素所标记的符号(每个符号都在栈中出现正好两次)。

    最初不存在相邻的两个元素符号相同的情况,保证有不超过 1 0 6 10^6 106 次操作的方案。

    输出格式

    第一行一个整数 m m m ,表示最小的移动次数。

    接下来 m m m 行,每行输出一个数。

    i + 1 i + 1 i+1 行输出 p i p_i pi,即表示玩家在第 i i i 步时选择交换 p i p_i pi p i + 1 p_{i+1} pi+1

    如果存在多个方案,则输出其中任何一个。

    样例 #1

    样例输入 #1

    5
    5
    2
    3
    1
    4
    1
    4
    3
    5
    2
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    样例输出 #1

    2
    5
    2
    
    • 1
    • 2
    • 3

    分析

    没有分析,把树状数组的模板改一下下就行了。

    代码

    #include 
     
    using namespace std;
    
    int lowbit(int x)//不要把lowbit忘了
    {
    	return x&-x;
    }
    
    long long n;
    
    long long ans,tot;
    
    long long t;
    
    long long tr[100000];
    
    long long a[100000],s[100000];
    
    long long x[1000005];
    
    
    void add(int x,int y)//写2个简简单单的函数就行了
    {
    	for(;x<=n*2;x+=lowbit(x)) 
    	{
    		tr[x]+=y;
    	}
    }
    
    long long aa(int x)
    {
    	long long num=0;
    	
    	for(;x;x-=lowbit(x))
    	{
    	 	num+=tr[x];
    	}
    	
    	return num;
    }
    
    int main()
    {
    	cin>>n;
    
    	for(int i=1;i<=n*2;i++) //输入
    	{
    		cin>>s[i];
    		
    		add(i,1);
    	}
    	
    	for(int i=1;i<=n*2;i++)
    	{
    		if(a[s[i]]==0)//如果当前元素还没遇到过,记录它的位置
    		{
    			a[s[i]]=i;
    		}
    		else//遇到过了
    		{
    			ans=ans+(aa(i)-aa(a[s[i]])-1);//统计步数,中间有几个,就要交换几次
    			
    			int k=i;
    			
    			int k2=aa(i-1)-aa(a[s[i]]);
    			
    			while(k2>0) 
    			{
    				x[++tot]=k-t-1;
    				
    				k--;
    				
    				k2--;
    			}
    	
    			add(a[s[i]],-1); 
    			add(i,-1); 
    			
                t+=2;//因为一次合并会消掉两个元素,所以t+=2
    		}
    	}
        
    	cout<<ans<<endl;
    	
    	for(int i=1;i<=tot;i++) 
    	{
    		cout<<x[i]<<endl;//输出
    	}
    	
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
  • 相关阅读:
    【Nginx】(五) Nginx作为微服务API网关的配置与应用
    标准C++中string类函数总结
    制造业数据标准化的优势分析
    【短文】Linux怎么读取文件大小
    使用kettle采集excel表格中的数据
    KNN实现鸢尾花分类
    6-1应用层-网络应用模型
    照片怎么压缩变小?
    Map接口遍历方法
    软件提示vcruntime140_1.dll丢失的解决方法,以及丢失的原因总结
  • 原文地址:https://blog.csdn.net/m0_66603329/article/details/126566760