1. 程式人生 > >BZOJ1106: [POI2007]立方體大作戰tet

BZOJ1106: [POI2007]立方體大作戰tet

sam mst 方塊 產生 php problems con pac zoj

題解:有點智商題 考慮到兩個位置直接沒有被消掉的必然會產生貢獻 所以一遍掃過去 用BIT維護兩個相同編號的木塊直接有多少個不同的即可

#include <bits/stdc++.h>
const int MAXN=5e4+10;
using namespace std;
int a[MAXN<<1],d[MAXN<<1],n;
int get_id(int x){return x&(-x);}
void add(int t,int vul){
    for(int i=t;i<=2*n;i+=get_id(i))d[i]+=vul;
}
int Sum(int x){
    int sum=0;
    for(int i=x;i>0;i-=get_id(i))sum+=d[i];
    return sum;
}
int vis[MAXN];
int main(){
    scanf("%d",&n);int ans=0;
    for(int i=1;i<=2*n;i++)scanf("%d",&a[i]);
    for(int i=1;i<=2*n;i++){
	add(i,1);
	if(!vis[a[i]])vis[a[i]]=i;
	else{
	    ans+=Sum(i-1)-Sum(vis[a[i]]);add(i,-1);add(vis[a[i]],-1);
	}
    }
    printf("%d\n",ans);
    return 0;
}

1106: [POI2007]立方體大作戰tet

Time Limit: 10 Sec Memory Limit: 162 MB
Submit: 877 Solved: 644
[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

BZOJ1106: [POI2007]立方體大作戰tet