zoukankan      html  css  js  c++  java
  • 【BZOJ1106】【POI2007】立方体大作战tet(贪心+树状数组/线段树优化区间和)

    1106: [POI2007]立方体大作战tet

    Time Limit: 10 Sec  Memory Limit: 162 MB
    Submit: 1103  Solved: 802
    [Submit][Status][Discuss]

    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
    样例输入2
    3
    1
    2
    3
    1
    2
    3

    Sample Output

    样例输出1
    2
    样例输出2
    3

    HINT

     


     

    发现1:两个相同数之间最少要移动 出现次数为单数的数字的个数 次才能相消,于是想到贪心,sort两个数之间至少移动次数(即前述的个数),按这个顺序消。

    发现2:不用sort,先消后消按什么顺序消并不影响,只要我们把最少移动次数=出现次数为单数的数字的个数,所以从左往右扫,树状数组维护一个区间和即可。

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<ctime>
    #include<cctype>
    #include<algorithm>
    #include<cstring>
    #include<iomanip>
    #include<queue>
    #include<map>
    #include<set>
    #include<bitset>
    #include<vector>
    #include<stack>
    #include<cmath>
    #include<bits/stdc++.h>
    #define ri register int
    #define ll long long
    #define For(i,l,r) for(ri i=l;i<=r;i++)
    #define Dfor(i,r,l) for(ri i=r;i>=l;i--)
    using namespace std;
    const int M=5e4+5;
    int n,a[M<<1],l[M<<1],t[M<<1],ans;
    inline ll read(){
        ll f=1,sum=0;
        char ch=getchar();
        while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
        while(isdigit(ch)){sum=(sum<<1)+(sum<<3)+(ch^48);ch=getchar();}
        return f*sum;
    }
    inline int query(int x){
        int sum=0;
        for(ri i=x;i;i-=i&(-i)){
            sum+=t[i];
        }
        return sum;
    }
    inline void add(int x,int val){
        for(ri i=x;i<=n<<1;i+=i&(-i)){
            t[i]+=val;
        }
    }
    int main(){
        n=read();
        For(i,1,n<<1) a[i]=read();
        For(i,1,n<<1){
            if(!l[a[i]]){
                add(i,1);l[a[i]]=i;
            }
            else{
                ans+=query(i)-query(l[a[i]]);
                add(l[a[i]],-1);
            }
        }
        printf("%d
    ",ans);
        return 0;
    }
  • 相关阅读:
    第36课 经典问题解析三
    第35课 函数对象分析
    67. Add Binary
    66. Plus One
    58. Length of Last Word
    53. Maximum Subarray
    38. Count and Say
    35. Search Insert Position
    28. Implement strStr()
    27. Remove Element
  • 原文地址:https://www.cnblogs.com/jian-song/p/11774057.html
Copyright © 2011-2022 走看看