[bzoj1106][亂搞]立方體大作戰tet
阿新 • • 發佈:2018-12-12
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
題解
顯然如果兩個數之間沒有兩個相同的數字 這兩個數要消掉,肯定至少要交換他們距離那麼多次 拿一個棧壓一下 消掉兩個數的代價,相當於他們的距離-他們之間能被消掉的數的對數 亂搞就好了
#include<cstdio> #include<cstring> #include<cstdlib> #include<algorithm> #include<cmath> #include<queue> #include<vector> #include<ctime> #include<map> #define LL long long #define mp(x,y) make_pair(x,y) using namespace std; inline int read() { int f=1,x=0;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } inline void write(int x) { if(x<0)putchar('-'),x=-x; if(x>9)write(x/10); putchar(x%10+'0'); } inline void print(int x){write(x);printf(" ");} int n,sta[51000],tp; int pos[51000],s[51000]; int lowbit(int x){return x&-x;} void change(int x,int c){for(int i=x;i<=n;i+=lowbit(i))s[i]+=c;} int findsum(int x){int ret=0;for(int i=x;i>=1;i-=lowbit(i))ret+=s[i];return ret;} int main() { n=read(); int ans=0; for(int i=1;i<=2*n;i++) { int x=read(); if(!pos[x])sta[++tp]=x,pos[x]=tp; else { ans+=tp-pos[x]-findsum(pos[x]); change(1,1);change(pos[x],-1); } } printf("%d\n",ans); return 0; }