BZOJ 3295: [Cqoi2011]动态逆序对 CDQ分治

3295: [Cqoi2011]动态逆序对


Description

对于序列A,它的逆序对数定义为满足i<j,且Ai>Aj的数对(i,j)的个数。给1到n的一个排列,按照某种顺序依次删除m个元素,你的任务是在每次删除一个元素之前统计整个序列的逆序对数。

Input

输入第一行包含两个整数nm,即初始元素的个数和删除的元素个数。以下n行每行包含一个1到n之间的正整数,即初始排列。以下m行每行一个正整数,依次为每次删除的元素。
 

Output

 
输出包含m行,依次为删除每个元素之前,逆序对的个数。

Sample Input

5 4
1
5
3
4
2
5
1
4
2

Sample Output

5
2
2
1

样例解释
(1,5,3,4,2)(1,3,4,2)(3,4,2)(3,2)(3)。

HINT

 

N<=100000 M<=50000

 

Source

 

 题解:
  CDQ分治第一题
 
#include<bits/stdc++.h>
using namespace std;
#pragma comment(linker, "/STACK:102400000,102400000")
#define ls i<<1
#define rs ls | 1
#define mid ((ll+rr)>>1)
#define pii pair<int,int>
#define MP make_pair
typedef long long LL;
const long long INF = 1e18+1LL;
const double pi = acos(-1.0);
const int N = 1e5+10, M = 1e3+20,inf = 2e9;

LL ans[N];
int n,m,c[N],mp[N];
struct ss{
    int t,x,y;
    bool operator < (const ss &r) const {
        return x == r.x? y < r.y : x < r.x;
    }
}a[N],t[N];
int cmp(ss s1,ss s2) {
    return s1.t==s2.t?s1.x < s2.x:s1.t<s2.t;
}
void add(int x,int cc) {
    for(int i = x; i <= n; i += i & (-i)) c[i] += cc;
}
int sum(int x) {
    int s = 0;
    for(int i = x; i; i -= i&(-i)) s += c[i];
    return s;
}
void cdq(int l,int r) {
    if(l == r) return ;
    int md = (l+r)>>1;
    cdq(l,md),cdq(md+1,r);
    int i = l, j = md+1,p = l;
    while(i<=md||j<=r) {
        if(j>r||(i<=md&&a[i] < a[j])) add(a[i].y,1),t[p++]=a[i++];
        else ans[a[j].t] += sum(n) - sum(a[j].y),t[p++]=a[j++];
    }
    for(int i = l; i <= md; ++i) add(a[i].y,-1);
    for(int i = l; i <= r; ++i) a[i] = t[i];
    for(int i = r; i >= l; --i) {
        if(a[i].t<=md) add(a[i].y,1);
        else ans[a[i].t] += sum(a[i].y);
    }
    for(int i = l; i <= r; ++i)
        if(a[i].t<=md) add(a[i].y,-1);
}
int main() {
    scanf("%d%d",&n,&m);
    for(int i = 1; i <= n; ++i) {
        int x;
        scanf("%d",&x);
        a[i].t =  0;
        a[i].x =  i;
        a[i].y =  x;
        mp[x] = i;
    }
    int Tim = n;
    for(int i = 1; i <= m; ++i) {
        int x;
        scanf("%d",&x);
        a[mp[x]].t = Tim--;
    }
    for(int i = 1; i <= n; ++i) {
        if(!a[i].t) a[i].t = Tim--;
    }
    sort(a+1,a+n+1,cmp);
    cdq(1,n);
    for(int i = 1; i <= n; ++i) ans[i] += ans[i-1];
    for(int i = n; i >= n-m+1; i--) printf("%lld\n",ans[i]);
    return 0;
}

 

  
posted @ 2017-07-14 16:00  meekyan  阅读(185)  评论(0编辑  收藏  举报