P3157 [CQOI2011] Dynamic reverse order (CDQ order to solve the problem of dimensional partial)

P3157 [CQOI2011] Dynamic reverse order

Title Description

For sequence A, which is defined as the logarithm of the reverse satisfy i <j, and Ai> Aj is the number of the number (i, j) of. Give a 1 to n are arranged, according to a certain order of m elements deleted, your task is to count the number of the entire reverse sequence of each deletion of an element before.

Input Format

Input of the first line contains two integers n and m, i.e., an initial number of elements and the number of elements removed. The following n lines contains a positive integer between 1 to n, i.e., initial alignment. The following m lines each a positive integer, followed by each element removed.

Output Format

Comprises m output lines, followed before deleting each element, the number of reverse order.

Sample input and output

Input # 1 copy

5 4
1
5
3
4
2
5
1
4
2

Output # 1 copy

5
2
2
1

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

Description / Tips

N<=100000 M<=50000

Ideas:

If you do not really understand CDQ, I suggest look at this.

CDQ divide and conquer to solve the problem and point to related

Then that is a very bare CDQ divide and conquer to solve the problem of three-dimensional partial order,

We know that the position of the reverse may be placed on a flat two-dimensional coordinate system, the point in the array is a pos x, y has a value of point

Two points $ (x1, y1) $, $ (x2, y2) $

If satisfied:

$ X1 <x2 $ while $ y1> y2 $

So this point is a reverse pair.

So three dimensions CDQ problem may be respectively:

Time, x coordinate, y coordinate.

The first solution to maintain direct sort, x coordinate resolve merge sort in ascending order, y coordinates of the array in a tree data structure solution.

Time complexity: $ O (n * log ^ 2 (n)) $

Code has some notes.

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <vector>
#include <iomanip>
#define ALL(x) (x).begin(), (x).end()
#define sz(a) int(a.size())
#define rep(i,x,n) for(int i=x;i<n;i++)
#define repd(i,x,n) for(int i=x;i<=n;i++)
#define pii pair<int,int>
#define pll pair<long long ,long long>
#define gbtb ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
#define MS0(X) memset((X), 0, sizeof((X)))
#define MSC0(X) memset((X), '\0', sizeof((X)))
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define eps 1e-6
#define gg(x) getInt(&x)
#define chu(x) cout<<"["<<#x<<" "<<(x)<<"]"<<endl
#define du3(a,b,c) scanf("%d %d %d",&(a),&(b),&(c))
#define du2(a,b) scanf("%d %d",&(a),&(b))
#define du1(a) scanf("%d",&(a));
using namespace std;
typedef long long ll;
ll gcd(ll a, ll b) {return b ? gcd(b, a % b) : a;}
ll lcm(ll a, ll b) {return a / gcd(a, b) * b;}
ll powmod(ll a, ll b, ll MOD) {a %= MOD; if (a == 0ll) {return 0ll;} ll ans = 1; while (b) {if (b & 1) {ans = ans * a % MOD;} a = a * a % MOD; b >>= 1;} return ans;}
void Pv(const vector<int> &V) {int Len = sz(V); for (int i = 0; i < Len; ++i) {printf("%d", V[i] ); if (i != Len - 1) {printf(" ");} else {printf("\n");}}}
void Pvl(const vector<ll> &V) {int Len = sz(V); for (int i = 0; i < Len; ++i) {printf("%lld", V[i] ); if (i != Len - 1) {printf(" ");} else {printf("\n");}}}

inline void getInt(int *p);
const int maxn = 1000010;
const int inf = 0x3f3f3f3f;
/*** TEMPLATE CODE * * STARTS HERE ***/
struct node {
    int t;
    int x;
    int y;
    node() {}
    node(int tt, int xx, int yy)
    {
        t = tt;
        x = xx;
        y = yy;
    }
    bool operator < (const node &bb )const
    {
        if (x != bb.x) {
            return x < bb.x;
        } else {
            return y < bb.y;
        }
    }
} a[maxn], b[maxn];
bool cmpx(node &aa, node &bb)
{
    return aa.t < bb.t;
}
int n, m;
int pos[maxn];
ll ans[maxn];

ll tree[maxn];
int lowbit(int x)
{
    return -x & x;
}
ll ask(int x)
{
    ll res = 0ll;
    while (x) {
        res += tree[x];
        x -= lowbit(x);
    }
    return res;
}
void add(int x, ll val)
{
    while (x < maxn) {
        tree[x] += val;
        x += lowbit(x);
    }
}
void clear(int x)
{
    while (x < maxn) {
        tree[x] = 0ll;
        x += lowbit(x);
    }
}
void cdq(int l, int r)
{
    if (l == r) {
        return ;
    }
    int mid = (l + r) >> 1;
    cdq(l, mid);
    cdq(mid + 1, r);
    int ql = l;
    int qr = mid + 1;
    // 计算在其左边,数值比其大的贡献
    //
    // 下面是类似归并排序方式计算贡献
    repd(i, l, r) {
        if (qr > r || (ql <= mid && a[ql] < a[qr])) {
            add(a[ql].y, 1);
            b[i] = a[ql++];
        } else {
            ans[a[qr].t] += ask(n) - ask(a[qr].y );
            b[i] = a[qr++];
        }
    }
    repd(i, l, mid) {
        clear(a[i].y);
    }
    repd(i, l, r) {
        a[i] = b[i];
    }
    // 计算在其右边,数值比其小的贡献
    // 因为上面已经归并排序过了,所以这个区间中是以x为升序的。
    for (int i = r; i >= l; --i) {
        if (a[i].t <= mid) {
            add(a[i].y, 1);
        } else {
            ans[a[i].t] += ask(a[i].y);
        }
    }
    repd(i, l, r) {
        clear(a[i].y);
    }
}
int main()
{
    //freopen("D:\\code\\text\\input.txt","r",stdin);
    //freopen("D:\\code\\text\\output.txt","w",stdout);
    du2(n, m);
    repd(i, 1, n) {
        a[i].x = i;
        du1(a[i].y);
        pos[a[i].y] = i;
    }
    int tm = n;
    repd(i, 1, m) {
        int x;
        du1(x);
        a[pos[x]].t = tm--;
    }
    repd(i, 1, n) {
        if (!a[i].t) {
            a[i].t = tm--;
        }
    }
    sort(a + 1, a + 1 + n, cmpx);// 按照time排序,确保时间维度time是升序的。
    cdq(1, n);
    repd(i, 1, n) {
        ans[i] += ans[i - 1];
    }
    for (int i = n; i >= n - m + 1; --i) {
        printf("%lld\n", ans[i]);
    }
    return 0;
}

inline void getInt(int *p)
{
    char ch;
    do {
        ch = getchar();
    } while (ch == ' ' || ch == '\n');
    if (ch == '-') {
        *p = -(getchar() - '0');
        while ((ch = getchar()) >= '0' && ch <= '9') {
            *p = *p * 10 - ch + '0';
        }
    } else {
        *p = ch - '0';
        while ((ch = getchar()) >= '0' && ch <= '9') {
            *p = *p * 10 + ch - '0';
        }
    }
}



Guess you like

Origin www.cnblogs.com/qieqiemin/p/11605173.html