bzoj 2141 : 排队 (cdq分治+bit)

链接: https://www.lydsy.com/JudgeOnline/problem.php?id=2141

思路:

其实就是求动态逆序对。。。cdq降维,用树状数组前后求两遍逆序对就好了

切水题真爽QAQ

实现代码:

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int M = 1e5+10;
int c[M<<2],a[M],b[M],ans[M];
int n,m;
struct node{
    int x,y,t;
    int kind,id;
    node(){}
    node(int a,int b,int c,int d,int e):t(a),x(b),y(c),kind(d),id(e){}
    bool operator < (const node &k) const {
        if(x == k.x) return t < k.t;
        return x < k.x;
    }
}q[M],t[M];

void add(int x,int val){
    while(x <= n){
        c[x] += val;
        x += (x&-x);
    }
}

int getsum(int x){
    int sum = 0;
    while(x){
        sum += c[x];
        x -= (x&-x);
    }
    return sum;
}

void cdq(int l,int r){
    if(l >= r) return ;
    int mid = (l + r) >> 1;
    for(int i = l;i <= r;i ++){
        if(q[i].t <= mid) add(q[i].y,q[i].kind);
        else ans[q[i].id] += q[i].kind*(getsum(n) - getsum(q[i].y));
    }
    for(int i = l;i <= r;i ++)
        if(q[i].t <= mid) add(q[i].y,-q[i].kind);

    for(int i = r;i >= l;i --){
        if(q[i].t <= mid) add(q[i].y,q[i].kind);
        else ans[q[i].id] += q[i].kind*(getsum(q[i].y-1));
    }
    for(int i = r;i >= l;i --)
        if(q[i].t <= mid) add(q[i].y,-q[i].kind);

    int L = l,R = mid+1;
    for(int i = l;i <= r;i ++){
        if(q[i].t <= mid) t[L++] = q[i];
        else t[R++] = q[i];
    }
    for(int i = l;i <= r;i ++) q[i] = t[i];
    cdq(l,mid); cdq(mid+1,r);
}

int main()
{
    scanf("%d",&n);
    for(int i = 1;i <= n;i ++){
        scanf("%d",&a[i]);
        b[i] = a[i];
    }
    int cnt = 0;
    sort(b+1,b+1+n);
    int len = unique(b+1,b+1+n)-b-1;
    for(int i = 1;i <= n;i ++){
        a[i] = lower_bound(b+1,b+len+1,a[i])-b;
        q[++cnt] = node(cnt,i,a[i],1,0);
    }
    scanf("%d",&m);
    for(int i = 1;i <= m;i ++){
        int x,y;
        scanf("%d%d",&x,&y);
        q[++cnt] = node(cnt,x,a[y],1,i);
        q[++cnt] = node(cnt,x,a[x],-1,i);
        q[++cnt] = node(cnt,y,a[x],1,i);
        q[++cnt] = node(cnt,y,a[y],-1,i);
        swap(a[x],a[y]);
    }
    sort(q+1,q+cnt+1);
    cdq(1,cnt);
    printf("%d\n",ans[0]);
    for(int i = 1;i <= m;i ++){
        ans[i] += ans[i-1];
    }
    for(int i = 1;i <= m;i ++)
        printf("%d\n",ans[i]);
}

 

posted @ 2018-08-24 16:53  冥想选手  阅读(171)  评论(0编辑  收藏  举报