先贪心,容易发现如果两个点中间没有点对,那么一定可以先把这两个点消掉
分析一下,就可以发现这样两个点的答案就是这两个点对中间不成对的点数量
扫描过去,线段树维护每一个点的权值(是否会被算入答案)即可
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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 }