[bzoj1106]立方体大作战

先贪心,容易发现如果两个点中间没有点对,那么一定可以先把这两个点消掉
分析一下,就可以发现这样两个点的答案就是这两个点对中间不成对的点数量
扫描过去,线段树维护每一个点的权值(是否会被算入答案)即可

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define N 100005
 4 #define L (k<<1)
 5 #define R (L+1)
 6 #define mid (l+r>>1)
 7 int n,x,ans,vis[N],f[N<<2];
 8 void update(int k,int l,int r,int x,int y){
 9     if (l==r){
10         f[k]=y;
11         return;
12     }
13     if (x<=mid)update(L,l,mid,x,y);
14     else update(R,mid+1,r,x,y);
15     f[k]=f[L]+f[R];
16 }
17 int query(int k,int l,int r,int x,int y){
18     if ((l>y)||(x>r))return 0;
19     if ((x<=l)&&(r<=y))return f[k];
20     return query(L,l,mid,x,y)+query(R,mid+1,r,x,y);
21 }
22 int main(){
23     scanf("%d",&n);
24     for(int i=1;i<=2*n;i++){
25         scanf("%d",&x);
26         if (!vis[x]){
27             update(1,1,2*n,i,1);
28             vis[x]=i;
29         }
30         else{
31             if (vis[x]<0)continue;
32             ans+=query(1,1,2*n,vis[x]+1,i-1);
33             update(1,1,2*n,vis[x],0);
34             vis[x]=-1;
35         }
36     }
37     printf("%d",ans);
38 }
View Code
原文地址:https://www.cnblogs.com/PYWBKTDA/p/12060370.html