zoukankan      html  css  js  c++  java
  • 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
    ",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);
        }
    }
    View Code
  • 相关阅读:
    IP地址分类
    Python 加密 shellcode 免杀
    java翻译到mono C#实现系列(2) mono实现GridView 横向滚动
    Hello Jexus(转并修改)
    @using (Html.BeginForm())和@{Html.BeginForm();}@{Html.EndForm();}对比
    FindLine把多行查找改为多行替换
    java翻译到mono C#实现系列(1) 重写返回键按下的事件
    mono 的System.Data.SqlClient小记录
    架构文件夹说明
    Xamarin Mono For Android 4.6.07004看不到新建android
  • 原文地址:https://www.cnblogs.com/registerzxr/p/5081848.html
Copyright © 2011-2022 走看看