BZOJ3295 dynamic reverse order CDQ / + dendritic array block

Meaning of the questions:

For sequence A, which is defined as the logarithm of the reverse satisfy $ i <j $, and \ (A_i> A_j \) number of \ ((i, j) \ ) number. Given \ (1 \) to the \ (n-\) is arranged in a sequentially deleted in a certain order \ (m \) elements, your task is to count the number of the entire reverse sequence of each deletion of an element before.

Input:

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:

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

solution:

A thought: CDQ Partition + Fenwick tree

First, delete the title that contains the query operation began with the idea of ​​anti added to the list one by one to calculate the contribution of impact, but in fact can be considered a direct positive significant, considering delete each point generated.

Reverse calculation method is commonly used for a query value Fenwick tree before its value is greater than the number of the small number and the number after the number.

So here we can consider a point \ ((x, y) \) represents the position x y is added to the value of a point, a point is added each time when we need is \ ([1, x-1 ] ) \ in \ (val> y \) the counted number of.

Since the operating time of the order, and also pay attention to the subject of the next range, so you can consider using CDQ partition.

With code footnote:

#include<bits/stdc++.h>
#define M 100005
#define ll long long
#define lowbit(x) (x&-x)
using namespace std;
int n,m,a[M],pos[M],del[M];
long long ans[M];
struct node {
    int t,id,pos,f;
    bool operator<(const node&_)const {
        if(pos!=_.pos)return pos<_.pos;//根据下标x排序
        return f>_.f;
    }
} A[M<<1];
struct Tree {
    ll cnt[M];
    void add(int x,int v) {
        while(x)cnt[x]+=v,x-=lowbit(x);
    }
    int sum(int x) {
        int res=0;
        while(x<=n)res+=cnt[x],x+=lowbit(x);
        return res;
    }
} T;
void CDQ(int l,int r) {
//  printf("%d %d\n",l,r);
    if(l>=r)return;
    int mid=(l+r)>>1;
    CDQ(l,mid),CDQ(mid+1,r);//先处理下面的,防止下面排序的操作产生影响
    sort(A+l,A+r+1);
    int tot=0;
    int now=0;
    for(int i=l; i<=r; i++) {//正着找大的,反着找小的
        if(A[i].t<=mid)T.add(a[A[i].pos],A[i].f);
        else ans[A[i].id]+=A[i].f*T.sum(a[A[i].pos]+1);
    }
    for(int i=l; i<=r; i++)if(A[i].t<=mid)T.add(a[A[i].pos],-A[i].f);
    for(int i=r; i>=l; i--) {
        if(A[i].t<=mid)T.add(a[A[i].pos],A[i].f);
        else ans[A[i].id]+=A[i].f*(T.sum(1)-T.sum(a[A[i].pos]));
    }
    for(int i=l; i<=r; i++)if(A[i].t<=mid)T.add(a[A[i].pos],-A[i].f);
}
int main() {
    scanf("%d%d",&n,&m);
    int sz=0;
    for(int i=1; i<=n; i++)scanf("%d",&a[i]),pos[a[i]]=i,del[a[i]]=0;//因为开始全部加入,所以用一个较小的0
    for(int i=1; i<=n; i++)A[++sz]=(node)<%sz,0,pos[a[i]],1%>;//加入为1 删除为0
    for(int i=1,x; i<=m; i++)scanf("%d",&x),A[++sz]=(node)<%sz,i,pos[x],-1%>;
    CDQ(1,sz);
    for(int i=1; i<=m; i++)ans[i]+=ans[i-1],printf("%lld\n",ans[i-1]);
    return 0;
}

Two ideas: Block + Fenwick tree

Query block number in each block is smaller than the value of the current values ​​is greater than the number of the number and the following

+ Because the update is larger than the query so its value is the number of \ (sum (pos [x] , n) -sum (pos [x], x) \)

After a while and then delete the time to subtract before and

If the block size is s

The complexity of the block query log (s) // Fenwick tree complexity

Complexity is s single query complexity \ ((\ frac {n} {s} * \ log n) \)

Therefore, the block size was set to \ (\ sqrt {n * \ log n} \)

#include<bits/stdc++.h>
using namespace std;
#define lowbit(x) (x&-x)
#define M 100005
int n,m,a[M],b[M],cnt[90][M],id[M];
long long tot[M],ans=0;
bool mark[M];
void add(int x,int k,int q) {
    while(x<=n)cnt[k][x]+=q,x+=lowbit(x);
}
int sum(int x,int k) {
    int res=0;
    while(x)res+=cnt[k][x],x-=lowbit(x);
    return res;
}
int main() {
    scanf("%d%d",&n,&m);
    memset(cnt,0,sizeof(cnt));
    int s=sqrt(n*log(n)/log(2));
    for(int i=1; i<=n; i++)scanf("%d",&a[i]),id[a[i]]=i;
    for(int i=1; i<=m; i++)scanf("%d",&b[i]);
    for(int i=1; i<=n; i++) {
        for(int j=i/s*s; j<i; j++)ans+=(a[j]>a[i]);
        for(int j=0; j<i/s; j++)ans+=sum(n,j)-sum(a[i],j);
        add(a[i],i/s,1);
    }
    for(int i=1; i<=m; i++) {
        int x=b[i];
        x=id[b[i]];
        printf("%lld\n",ans);
        for(int j=x+1; j<=min((x/s+1)*s-1,n); j++)ans-=(!mark[j])*(a[j]<a[x]);
        for(int j=x/s+1; j<=n/s; j++)ans-=sum(a[x],j);
        for(int j=x/s*s; j<x; j++)ans-=(!mark[j])*(a[j]>a[x]);
        for(int j=0; j<x/s; j++)ans-=sum(n,j)-sum(a[x],j);
        add(a[x],x/s,-1);
        mark[x]=1;
    }
    return 0;
}

Guess you like

Origin www.cnblogs.com/cly1231/p/10981184.html