树套树呀树套树。
题意为可以交换两个位置的数,询问每次交换后的逆序对数。直接区间线段树上面套一个值域线段树,然后稍微讨论一下。
首先建好树查询一次得到一个ans。(话说我们得到了一个nlog^2的求逆序对的算法)
设两个位置为i,j,如果i==j或者是a[i] == b[j]的话就不管。i>j则交换。如果j==i+1的话直接交换更新答案(我交换是删两次加两次)。否则的话从i+1到j-1改几次。上代码,,应该很好看懂
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <cstdio> #include <map> #include <iostream> #include <algorithm> using namespace std; const int N = 20003; int n,a[N],b[N],T = 0,t1,t2,m; map<int,int>hero; struct tree1 { tree1* lson; tree1* rson; int cnt; tree1() { lson = rson = NULL; cnt = 0; } }dizhi1[N*300]; struct tree2 { tree2* lson; tree2* rson; tree1* on_tree; tree2() { lson = rson = NULL; on_tree = NULL; } }*root,dizhi2[N*3]; inline void insert(tree1* tree,int l,int r,int pos,int x) { if(l==r) { tree->cnt += x; return; } int mid = (l+r)>>1; if(pos <= mid) { if(tree->lson==NULL) tree->lson = &dizhi1[++t1]; insert(tree->lson,l,mid,pos,x); } else { if(tree->rson==NULL) tree->rson = &dizhi1[++t1]; insert(tree->rson,mid+1,r,pos,x); } tree->cnt = 0; if(tree->lson!=NULL) tree->cnt += tree->lson->cnt; if(tree->rson!=NULL) tree->cnt += tree->rson->cnt; } inline void build(tree2* tree,int l,int r) { tree->on_tree = &dizhi1[++t1]; for(int i = l ; i <= r ; ++i) insert(tree->on_tree,1,T,a[i],1); if(l==r) return; int mid = (l+r)>>1; tree->lson = &dizhi2[++t2]; tree->rson = &dizhi2[++t2]; build(tree->lson,l,mid); build(tree->rson,mid+1,r); } inline int query2(tree1* tree,int l,int r,int x,int y) { if(x<=l && r<=y) return tree->cnt; int mid = (l+r)>>1; int q1 = 0, q2 = 0; if(!(y<l||mid<x) && tree->lson!=NULL) q1 = query2(tree->lson,l,mid,x,y); if(!(y<mid+1||r<x) && tree->rson!=NULL) q2 = query2(tree->rson,mid+1,r,x,y); return (q1+q2); } inline int query(tree2* tree,int l,int r,int x,int y,int c,bool zxr_handsome) { if(x<=l && r<=y) { if(zxr_handsome) return query2(tree->on_tree,1,T,c+1,T); else return query2(tree->on_tree,1,T,1,c-1); } int mid = (l+r)>>1; int q1 = 0,q2 = 0; if(!(y<l||mid<x)) q1 = query(tree->lson,l,mid,x,y,c,zxr_handsome); if(!(y<mid+1||r<x)) q2 = query(tree->rson,mid+1,r,x,y,c,zxr_handsome); return (q1+q2); } inline void modify(tree2* tree,int l,int r,int pos,int v,int add) { insert(tree->on_tree,1,T,v,add); if(l==r) return; int mid = (l+r)>>1; if(pos <= mid) modify(tree->lson,l,mid,pos,v,add); else modify(tree->rson,mid+1,r,pos,v,add); } int ans = 0; int main() { scanf("%d",&n); for(int i = 1 ; i <= n ; ++i) scanf("%d",&a[i]),b[i] = a[i]; sort(b+1,b+1+n); hero[b[1]] = ++T; for(int i = 2 ; i <= n ; ++i) if(b[i]!=b[i-1]) hero[b[i]] = ++T; for(int i = 1 ; i <= n ; ++i) a[i] = hero[a[i]]; root = &dizhi2[++t2]; build(root,1,n); for(int i = 2 ; i <= n ; ++i) if(a[i]!=T) ans += query(root,1,n,1,i-1,a[i],1); printf("%d ",ans); scanf("%d",&m); for(int i = 1 ; i <= m ; ++i) { int x,y; scanf("%d%d",&x,&y); if(x>y) swap(x,y); if(x==y||a[x]==a[y]) { printf("%d ",ans); continue; } if(x+1==y) { if(a[x] > a[y]) ans--; else ans++; modify(root,1,n,x,a[x],-1); modify(root,1,n,y,a[y],-1); modify(root,1,n,y,a[x],1); modify(root,1,n,x,a[y],1); swap(a[x],a[y]); printf("%d ",ans); continue; } if(a[x] > a[y]) ans--; else ans++; if(a[x]!=T)ans += query(root,1,n,x+1,y-1,a[x],1); if(a[x]!=1)ans -= query(root,1,n,x+1,y-1,a[x],0); if(a[y]!=1)ans += query(root,1,n,x+1,y-1,a[y],0); if(a[y]!=T)ans -= query(root,1,n,x+1,y-1,a[y],1); modify(root,1,n,x,a[x],-1); modify(root,1,n,y,a[y],-1); modify(root,1,n,y,a[x],1); modify(root,1,n,x,a[y],1); swap(a[x],a[y]); printf("%d ",ans); } }