BZOJ3295 CQOI2011 Dynamic Inverse Sequence Pair

3295: [Cqoi 2011] Dynamic reverse pair

Time Limit: 10 Sec  Memory Limit: 128 MB

Description

For sequence A, its inverse logarithm is defined as the number of pairs (i,j) satisfying I < J and Ai > Aj.
Given an arrangement of 1 to n, delete m elements in some order.
Your task is to count the inverse logarithm of the entire sequence before deleting one element at a time.

Input

The first line of input contains two integers n and m, that is, the number of initial elements and the number of deleted elements.
The following n rows contain a positive integer between 1 and n, which is the initial arrangement.
The following m lines have a positive integer for each line, followed by each deleted element.

Output 

The output contains m rows, in turn the number of reverse pairs before deleting each element.

Sample Input

5 4

1 5 3 4 2

5 1 4 2

 

Sample Output

5
2
2
1
Sample explanation
(1,5,3,4,2) (1,3,4,2) (3,4,2) (3,2) (3).

HINT 

N<=100000 M<=50000

I didn't see CDQ at that time, but I pointed out the tree sheath, but I just couldn't write it.

It still seems obvious.

For the number in the arrangement, remember that the time it was deleted is t (the undeleted is set to m+1), the subscript is X, and the size is Y.

For a number i, see how much the number deleted before it decreases the answer to it:

    Σ(Tj<Ti && Xj<Xi && Yj>Yi) + Σ(Tj<Ti && Xj>Xi && Yj<Yi)

Do CDQ twice. This kind of calculation without repetition is really cool.

It's not good to do without draft paper.

#include    <iostream>
#include    <cstdio>
#include    <cstdlib>
#include    <algorithm>
#include    <vector>
#include    <cstring> 
using namespace std;
 
const int N = 100010;
struct Data{
    int X,Y,T;long long len;
    bool operator <(const Data &t)const{
        return T<t.T;
    }
}rem[N],f[N],t[N];
int n,m,ban[N],bplace[N],A[N],T[N];
long long Ans,ans[N];
 
inline int gi()
{
    int x=0,res=1;char ch=getchar();
    while(ch>'9' || ch<'0'){if(ch=='-')res=-res;ch=getchar();}
    while(ch>'/' && ch<':')x=x*10+ch-48,ch=getchar();
    return x*res;
}
 
inline int lb(int k){return k&-k;}
 
inline void update(int x){for(;x<=n;x+=lb(x))T[x]++;}
 
inline int query(int x)
{
    int ans=0;
    for(;x;x-=lb(x))ans+=T[x];
    return ans;
}
 
inline void clean(int x){for(;x<=n;x+=lb(x))T[x]=0;}
 
inline void calc()
{
    memset(T,0,sizeof(T));Ans=0;
    for(int i=1;i<=n;++i){
        Ans+=(i-query(A[i])-1);
        update(A[i]);
    }
    memset(T,0,sizeof(T));
}
//Ensure T order outside, X order within CDQ, and Y value statistics. 
//T: Time X: Location Y: Weight
//CDQ calc Ti<Tj Xi<Xj Y[i]<Y[j]
inline void CDQ(int l,int r)
{
    if(l==r)return;int mid=(l+r)>>1;
    CDQ(l,mid);CDQ(mid+1,r);
    int x=l,y=mid+1,z=l;
    while(x<=mid && y<=r)
        if(f[x].X<f[y].X)update(f[x].Y),t[z++]=f[x++];
        else f[y].len+=query(f[y].Y),t[z++]=f[y++];
    while(x<=mid)t[z++]=f[x++];
    while(y<=r)f[y].len+=query(f[y].Y),t[z++]=f[y++];
    for(int i=l;i<=mid;++i)clean(f[i].Y);
    for(int i=l;i<=r;++i)f[i]=t[i];
}
 
int main()
{
    n=gi();m=gi();
    for(int i=1;i<=n;++i)
        A[i]=gi();
    for(int i=1;i<=m;++i)
        bplace[ban[i]=gi()]=i;
    for(int i=1;i<=n;++i){
        rem[i].T=bplace[A[i]];
        rem[i].X=i;
        rem[i].Y=A[i];
        if(!rem[i].T)rem[i].T=m+1;
    }
    sort(rem+1,rem+n+1);calc();
    for(int i=0;i<=m;++i)ans[i]=Ans;
    for(int i=1;i<=n;++i){
        f[i]=rem[i];
        f[i].Y=n-f[i].Y+1;
    }
    reverse(f+1,f+n+1);
    CDQ(1,n);sort(f+1,f+n+1);
    for(long long i=1,s=0;i<=n;++i){
        if(!f[i].T)continue;
        ans[f[i].T]-=s;s+=f[i].len;
    }
    for(int i=1;i<=n;++i){
        f[i]=rem[i];
        f[i].X=n-f[i].X+1;
    }
    reverse(f+1,f+n+1);
    CDQ(1,n);sort(f+1,f+n+1);
    for(long long i=1,s=0;i<=n;++i){
        if(!f[i].T)continue;
        ans[f[i].T]-=s;s+=f[i].len;
    }
    for(int i=1;i<=m;++i)
        printf("%lld\n",ans[i]);
    return 0;
}

  

Then see my partition in ancient times??!!

His face was blurred.

I stared for a long time and found that I didn't write it.

Perhaps the idea is to divide the blocks and sort them within each block.

Then inquire:

It's not in your own block. Divide it in half.

In my own part, violence is involved.

Then delete it.

6000ms... gone by...

Amboli Pollution Wave.

#include <cstdio>  
#include <cmath>  
#include <cstdlib>  
#include <algorithm>  
#include <cstring>  
using namespace std;  
#define ll long long  
const int N=200050;  
int n,m,a[N];  
int tmp[N],t[N];//merge-sort  
int belong[N],L[N],R[N],cnt,k,x,y;  
int ad[N];      //The position of I in the primitive sequence is ad[i]    
int b[N];       //Each block maintains an ordered sequence of numbers   
int sum[N];     //How many deletions have been made in the current block   
int adx;  
int i;  
bool f[N];  
ll tot;        //The current inverse logarithm opens long!   
inline int get(){  
  int p=0;char x=getchar();  
  while (x<'0' || x>'9') x=getchar();  
  while (x>='0' && x<='9') p=p*10+x-'0',x=getchar();  
  return p;  
}  
inline void merge_sort(int l,int r){  
  int mid,p,i,j;  
  mid=(l+r)>>1;  
  i=p=l;j=mid+1;  
  while (i<=mid && j<=r)  
    if (tmp[i]>tmp[j]) t[p++]=tmp[j++],tot+=mid-i+1;  
    else t[p++]=tmp[i++];  
  while (i<=mid) t[p++]=tmp[i++];  
  while (j<=r) t[p++]=tmp[j++];  
  for (i=l;i<=r;i++) tmp[i]=t[i];  
  return ;  
}  
inline void merge(int l,int r){  
  if (l>=r) return ;  
  int mid=(l+r)>>1;  
  merge(l,mid);  
  merge(mid+1,r);  
  merge_sort(l,r);  
  return ;  
}  
void init(){  
  n=get();m=get();  
  k=sqrt(n);      //Block size   
  cnt=n/k;if (n%k) cnt++; //Number of blocks   
  for (int i=1;i<=n;i++)  
    a[i]=get(),ad[a[i]]=i,belong[i]=(i-1)/k+1;  
  for (int i=1;i<=cnt;i++)  
    L[i]=i*k-k+1,R[i]=i*k;  
  R[cnt]=n;  
  memcpy(tmp,a,sizeof tmp); 
  tot=0;  
  merge(1,n);  
  memcpy(b,a,sizeof a);  
  for (int i=1;i<=cnt;i++)  
    sort(b+L[i],b+R[i]+1);  
  memset(f,1,sizeof f);  
  return ;  
}  
inline int search(int t,int p){  
  int l,r,ret;  
  l=L[t]; r=R[t]; ret=R[t];  
  while (l<=r){  
    int mid=(l+r)>>1;  
    if (b[mid]<=p) ret=mid,l=mid+1;  
    else r=mid-1;  
  }  
  if (b[ret]>p) ret=L[i]-1;  
  return ret;  
}  
int main(){
  init();  
  for (int p=1;p<=m;p++){  
    printf("%lld\n",tot);  
    y=get();x=ad[y];        //The numbering of the blocks where the positions in the a-Series are obtained is invariable.  
    k=belong[x];            //x belongs to block k     
    for (i=1;i<k;i++)  
      tot-=R[i]-search(i,a[x]);  
    for (i=k+1;i<=cnt;i++)  
      tot-=search(i,a[x])-L[i]+1-sum[i];  
    for (i=L[k];i<x;i++)  
      if (f[a[i]] && a[i]>a[x]) tot--;  
    for (i=x+1;i<=R[k];i++)  
      if (f[a[i]] && a[i]<a[x]) tot--;  
    adx=search(k,a[x]);  
    b[adx]=0;sum[k]++;  
    f[a[x]]=0;  
    sort(b+L[k],b+R[k]+1);  
  }  
  return 0;  
}

  

Keywords: C++

Added by ginginca on Sun, 09 Jun 2019 03:22:14 +0300