zoukankan      html  css  js  c++  java
  • UVA 11990 ``Dynamic'' Inversion (线段树套BIT,分治)

    题目要求可转化为查询一个区间内有多少数比val大(或者小)。

    区间用线段树分解(logN),每个区间维护一rank树。

    rank可用BIT查询,往BIT里面插值,为了保证不同区间的BIT互不影响要先离散。

    首先进行分治,分治的同时归并排序完成离散并计算保存出每个元素和其他元素构成的逆序对iv[i]。(据说这叫归并树

    初始值将所有iv求和,一个对被算了两次所以除以二。

    每次删除元素val就减去val对应的逆序对。

    减去iv[val],但是多减去了和之前删掉元素构成的逆序对(这些逆序对已经算过一次)。

    所以把删掉的元素加到线段树里面。

    减去当前iv[val]之后,查询并加上当前元素val和之前位置以及之后位置构成逆序对。

    复杂度

    O(nlogn)预处理,O(m*logn*logn)回答

    #include<bits/stdc++.h>
    using namespace std;
    
    
    const int maxn = 2e5+5, LogN = 20;
    
    typedef long long ll;
    ll invPair;
    int a[maxn],p[maxn];
    int iv[maxn];
    int n;
    
    int s[maxn<<2];
    int C[LogN][maxn];
    int Set[LogN][maxn];
    
    #define para int o = 1, int l = 1,int r = n,int dep = 0
    #define lo (o<<1)
    #define ro (o<<1|1)
    #define TEMP int mid = (l+r)>>1, lc = lo, rc = ro;
    #define lsn lc, l, mid, dep+1
    #define rsn rc, mid+1, r, dep+1
    
    #define lb(x) ((x)&-(x))
    int sum(int C[],int x)
    {
        int re = 0;
        while(x>0){
            re += C[x];
            x -= lb(x);
        }
        return re;
    }
    
    void add(int C[],int x,int d,int r)
    {
        while(x<=r){
            C[x] += d;
            x += lb(x);
        }
    }
    
    int qpos;
    int ql,qr,val;
    void queryPrefix(para)
    {
        if(1<=l&&r<=qr){
            int pos = upper_bound(Set[dep]+l,Set[dep]+r+1,val)-Set[dep]-l;//等于等于val的最大元素的编号
            invPair += s[o] - sum(C[dep]+l-1,pos);//得到大于val的元素个数
        }else {
            TEMP
            queryPrefix(lsn);
            if(qr>mid) queryPrefix(rsn);
        }
    }
    
    void querySuffix(para)
    {
        if(ql<=l&&r<=n){
            int pos = lower_bound(Set[dep]+l,Set[dep]+r+1,val)-Set[dep]-l;//严格小于val的元素的编号
            invPair += sum(C[dep]+l-1,pos);
        }else {
            TEMP
            if(ql<=mid) querySuffix(lsn);
            querySuffix(rsn);
        }
    }
    
    
    void modify(para)
    {
        s[o]++;
        if(l == r){
            C[dep][l] = 1;
        }else{
            TEMP
            if(qpos<=mid) modify(lsn);
            else modify(rsn);
            int pos = upper_bound(Set[dep]+l,Set[dep]+r+1,val)-Set[dep]-l;//val在set里,从1开始编号
            add(C[dep]+l-1,pos,1,r-l+1);//l-1是0号位,容纳r-l+1个元素
        }
    }
    
    
    //为保证BIT之间互不影响,merge_sort离散,同时计算逆序对
    void discretize(para)
    {
        s[o] = 0;
        memset(C[dep]+l,0,sizeof(int)*(r-l+1));
        if(l == r) {
            Set[dep][l] = a[l];
            return;
        }else {
            TEMP;
            discretize(lsn);
            discretize(rsn);
            int p = l, q = mid+1, k = l;
            while(p<=mid || q<=r){
                if(q > r|| (p <= mid && Set[dep+1][p] <= Set[dep+1][q]) ){
                    iv[Set[dep+1][p]] += k-p;//和后面的数构成逆序对
                    Set[dep][k++] = Set[dep+1][p++];
                }else {
                    iv[Set[dep+1][q]] += mid-p+1;//和前面的数构成逆序对
                    Set[dep][k++] = Set[dep+1][q++];
                }
            }
        }
    }
    
    //#define LOCAL
    int main()
    {
    #ifdef LOCAL
        freopen("in.txt","r",stdin);
    #endif
        int m;
        while(~scanf("%d%d",&n,&m)){
            memset(iv+1,0,sizeof(int)*n);
            for(int i = 1; i <= n; i++){
                scanf("%d",a+i);
                p[a[i]] = i;
            }
            invPair = 0;
            discretize();
            for(int i = 1; i <= n; i++){
                invPair += iv[i];
            }
            invPair >>= 1;
            while(m--){
                scanf("%d",&val);
                printf("%lld
    ",invPair);
                invPair -= iv[val];
                qr = p[val]-1;
                ql = p[val]+1;
                if(qr>=1) queryPrefix();
                if(ql<=n) querySuffix();
                qpos = p[val];
                modify();
            }
        }
        return 0;
    }
  • 相关阅读:
    获取元素位置信息和所占空间大小(via:js&jquery)
    原生js获取元素的样式信息
    真的了解js生成随机数吗
    js中有关滑动问题的一些理解
    禁止遮罩层以下屏幕滑动----正解(更新版)
    js中的null和undefined
    通过ajax获得json数据后格式的转换
    悬浮导航栏的实现以及导航跳转
    css selector
    视频播放器
  • 原文地址:https://www.cnblogs.com/jerryRey/p/4861214.html
Copyright © 2011-2022 走看看