BZOJ_2141

树套树呀树套树。

题意为可以交换两个位置的数,询问每次交换后的逆序对数。直接区间线段树上面套一个值域线段树,然后稍微讨论一下。

首先建好树查询一次得到一个ans。(话说我们得到了一个nlog^2的求逆序对的算法)

设两个位置为i,j,如果i==j或者是a[i] == b[j]的话就不管。i>j则交换。如果j==i+1的话直接交换更新答案(我交换是删两次加两次)。否则的话从i+1到j-1改几次。上代码,,应该很好看懂

#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\n",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\n",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\n",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\n",ans);
    }
}
View Code

 

posted @ 2015-12-28 10:46  443singer  阅读(106)  评论(0编辑  收藏  举报