[P1393 Dynamic Inverse Pairs] Tree Array Set Dynamic Open-Point Line Segment Tree + Tree Array

Keywords: Linker iOS

P1393
This topic lays a foundation for the division and conquer of CDQ.
Let's start with how this blog works.
We need to know that the number of inverse pairs whose answers are reduced by deleting a number is equal to the value of the coordinates in front of the deleted number is larger than mine.
The value of the coordinates after this number is smaller than mine.
So we can use the tree array to find the original O(n).
Then the tree array is used to nest the dynamic open-point segment tree, which can be maintained by O(log^2n) and queried with the same complexity.
So I just subtract online and output the answer.
Offline practice of writing a CDQ version later

/*
    if you can't see the repay
    Why not just work step by step
    rubbish is relaxed
    to ljq
*/
#include <cstdio>
#include <cstring>
#include <iostream>
#include <queue>
#include <cmath>
#include <map>
#include <stack>
#include <set>
#include <sstream>
#include <vector>
#include <stdlib.h>
#include <algorithm>
//#pragma comment(linker, "/STACK:10240000,10240000")
using namespace std;

#define dbg(x) cout<<#x<<" = "<< (x)<< endl
#define dbg2(x1,x2) cout<<#x1<<" = "<<x1<<" "<<#x2<<" = "<<x2<<endl
#define dbg3(x1,x2,x3) cout<<#x1<<" = "<<x1<<" "<<#x2<<" = "<<x2<<" "<<#x3<<" = "<<x3<<endl
#define max3(a,b,c) max(a,max(b,c))
#define min3(a,b,c) min(a,min(b,c))

typedef pair<int,int> pll;
typedef long long ll;
typedef unsigned long long ull;
const ull hash1 = 201326611;
const int inf = 0x3f3f3f3f;
const int _inf = 0xc0c0c0c0;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const ll _INF = 0xc0c0c0c0c0c0c0c0;
const ll mod =  (int)1e9+7;

ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
ll ksm(ll a,ll b,ll mod){ll ans=1;while(b){if(b&1) ans=(ans*a)%mod;a=(a*a)%mod;b>>=1;}return ans;}
ll inv2(ll a,ll mod){return ksm(a,mod-2,mod);}
void exgcd(ll a,ll b,ll &x,ll &y,ll &d){if(!b) {d = a;x = 1;y=0;}else{exgcd(b,a%b,y,x,d);y-=x*(a/b);}}//printf("%lld*a + %lld*b = %lld\n", x, y, d);
//ull ha[MAX_N],pp[MAX_N];

inline int read()
{
    int date = 0,m = 1; char ch = 0;
    while(ch!='-'&&(ch<'0'|ch>'9'))ch = getchar();
    if(ch=='-'){m = -1; ch = getchar();}
    while(ch>='0' && ch<='9')
    {
        date = date*10+ch-'0';
        ch = getchar();
    }return date*m;
}
const int MAX_N = 40025;
int C[MAX_N<<1],rt[MAX_N*50],arr[MAX_N],cnt[MAX_N],cnt_[MAX_N],b[MAX_N];
int n,m,siz;
struct node{int l,r,sum;}T[MAX_N*50];
void add(int x,int v )
{
    for(;x<MAX_N;x+=x&(-x))
        C[x]+=v;
}
int get(int x)
{
    int res = 0;
    for(;x;x-=x&(-x))
        res+=C[x];
    return res;
}
void update(int &p,int l,int r,int pos)
{
    if(!p) p = ++siz;
    ++T[p].sum;
    if(l==r) return ;
    int mid = (l+r)>>1;
    if(pos<=mid) update(T[p].l,l,mid,pos);
    else update(T[p].r,mid+1,r,pos);
}
int query(int p,int l,int r,int x,int y)
{
    if(x>r||y<l) return 0;
    if(x<=l&&r<=y) return T[p].sum;
    int mid = (l+r)>>1;
    return query(T[p].l,l,mid,x,y)+query(T[p].r,mid+1,r,x,y);
}
ll ask(int l,int r,int x,int y)
{
    if(x>y) return 0;
    ll res = 0;
    for(;l;l-=l&(-l)) res-=query(rt[l],1,n,x,y);
    for(;r;r-=r&(-r)) res+=query(rt[r],1,n,x,y);
    return res;
}
/*namespace sgt
{
    #define mid ((l+r)>>1)

    #undef mid
}*/

/*int root[MAX_N],cnt,sz;
namespace hjt
{
    #define mid ((l+r)>>1)
    struct node{int l,r,maxx;}T[MAX_N*40];

    #undef mid
}*/

int main()
{
    //ios::sync_with_stdio(false);
    //freopen("a.txt","r",stdin);
    //freopen("b.txt","w",stdout);
    ll ans = 0;
    n = read();m = read();
    for(int i = 1;i<=n;++i)
    {
        arr[i] = read();
        b[i] = arr[i];
    }
    sort(b+1,b+1+n);
    for(int i = 1;i<=n;++i)
    {
        arr[i] = lower_bound(b+1,b+1+n,arr[i])-b;
        cnt[i] = i - 1 - get(arr[i]);
        ans +=cnt[i];
        add(arr[i],1);
    }
    for(int i =1 ;i<MAX_N*2;++i)
        C[i] = 0;
    for(int i = n;i>=1;--i)
    {
        cnt_[i] = get(arr[i]);
        add(arr[i],1);
    }
    for(int i = 1;i<=m;++i)
    {
        printf("%lld ",ans);
        int pos;
        pos = read();
        ans-=(cnt[pos]+cnt_[pos])-ask(0,pos,arr[pos]+1,n)-ask(pos,n,1,arr[pos]-1);
        for(int j = pos;j<=n;j+=j&(-j))
            update(rt[j],1,n,arr[pos]);
    }
    printf("%lld\n",ans);
    //fclose(stdin);
    //fclose(stdout);
    //cout << "time: " << (long long)clock() * 1000 / CLOCKS_PER_SEC << " ms" << endl;
    return 0;
}

Posted by Zhadus on Fri, 04 Oct 2019 08:36:34 -0700