【刷題】BZOJ 3295 [Cqoi2011]動態逆序對
阿新 • • 發佈:2018-03-23
順序 fin sizeof put bit ons 就是 mat getchar()
(1,5,3,4,2)?(1,3,4,2)?(3,4,2)?(3,2)?(3)。
位置上的權值大的個數,\(Lquery(i)\) 表示的就是後面的比它小的已經刪除了的個數
既然 \(A1\) 和 \(A2\) 已經預處理好了
那麽我們需要維護的就是兩個查詢了
我們想,假如沒有修改,那麽兩個查詢直接用主席樹找就行了
那麽有修改呢,我們需要為主席樹提供的就是前綴和
所以就用樹狀數組去維護前綴和,類似於 BZOJ 1901 Zju2112 Dynamic Rankings 用一個樹套樹,這道題就搞定了
Description
對於序列A,它的逆序對數定義為滿足i
Input
輸入第一行包含兩個整數n和m,即初始元素的個數和刪除的元素個數。
以下n行每行包含一個1到n之間的正整數,即初始排列。
以下m行每行一個正整數,依次為每次刪除的元素。
N<=100000 M<=50000
Output
輸出包含m行,依次為刪除每個元素之前,逆序對的個數。
Sample Input
5 4
1
5
3
4
2
5
1
4
2
Sample Output
5
2
2
1
HINT
樣例解釋
Solution
樹套樹,樹狀數組套主席樹
首先看問題
我們預處理出\(A1[i]\)(\(i\) 之前的位置上的數比 \(i\) 位置上的數大的個數),\(A2[i]\)(\(i\) 之後的位置上的數比 \(i\) 位置上的數小的個數),順便求一下最開始的逆序對
那麽我們每次刪除一個數 \(x\) ,它在數列中的位置是 \(i\) ,那麽它對答案產生的影響就是使答案減小 \(A1[i]+A2[i]-Mquery(i)-Lquery(i)\)
其中 \(Mquery(i)\) 表示的是 \(i\) 位置之前的已經被刪除了的權值比 \(i\)
既然 \(A1\) 和 \(A2\) 已經預處理好了
那麽我們需要維護的就是兩個查詢了
我們想,假如沒有修改,那麽兩個查詢直接用主席樹找就行了
那麽有修改呢,我們需要為主席樹提供的就是前綴和
所以就用樹狀數組去維護前綴和,類似於 BZOJ 1901 Zju2112 Dynamic Rankings 用一個樹套樹,這道題就搞定了
#include<bits/stdc++.h> #define ll long long #define db double #define ld long double #define left 0 #define right 1 #define Mid ((l+r)>>1) #define lson l,Mid #define rson Mid+1,r const int MAXN=100000+10; int n,m,A[MAXN],A1[MAXN],A2[MAXN],pos[MAXN]; ll ans=0; struct BI_Tree{ int C[MAXN]; inline void init() { memset(C,0,sizeof(C)); } inline int lowbit(int x) { return x&(-x); } inline int sum(int x) { int res=0; while(x>0) { res+=C[x]; x-=lowbit(x); } return res; } inline void add(int x,int k) { while(x<=n) { C[x]+=k; x+=lowbit(x); } } }; BI_Tree BIT; struct ChairManTree_BIT{ int cnt,lc[MAXN*50],rc[MAXN*50],root[MAXN],nt[2],need[2][MAXN]; ll num[MAXN*50]; inline void init() { cnt=0; memset(lc,0,sizeof(lc)); memset(rc,0,sizeof(rc)); memset(num,0,sizeof(num)); } inline int lowbit(int x) { return x&(-x); } inline void Insert(int &rt,int l,int r,int pos) { if(!rt)rt=++cnt; num[rt]++; if(l==r)return ; else { if(pos<=Mid)Insert(lc[rt],lson,pos); else Insert(rc[rt],rson,pos); } } inline void add(int x,int k) { while(x<=n) { Insert(root[x],1,n,k); x+=lowbit(x); } } inline void Gneed(int nxt[]) { for(register int i=1;i<=nt[left];++i)need[left][i]=nxt[need[left][i]]; for(register int i=1;i<=nt[right];++i)need[right][i]=nxt[need[right][i]]; } inline int Lquery(int l,int r,int k) { if(l==r)return 0; else { ll res=0; if(k>Mid) { for(register int i=1;i<=nt[right];++i)res+=num[lc[need[right][i]]]; for(register int i=1;i<=nt[left];++i)res-=num[lc[need[left][i]]]; Gneed(rc); res+=Lquery(rson,k); } else { Gneed(lc); res+=Lquery(lson,k); } return res; } } inline ll Mquery(int l,int r,int k) { if(l==r)return 0; else { ll res=0; if(k<=Mid) { for(register int i=1;i<=nt[right];++i)res+=num[rc[need[right][i]]]; for(register int i=1;i<=nt[left];++i)res-=num[rc[need[left][i]]]; Gneed(lc); res+=Mquery(lson,k); } else { Gneed(rc); res+=Mquery(rson,k); } return res; } } inline ll sum(int l,int r,int k,int opt) { nt[left]=nt[right]=0; l--; while(l>0) { need[left][++nt[left]]=root[l]; l-=lowbit(l); } while(r>0) { need[right][++nt[right]]=root[r]; r-=lowbit(r); } if(opt==0)return Lquery(1,n,k); else return Mquery(1,n,k); } }; ChairManTree_BIT T; template<typename T> inline void read(T &x) { T data=0,w=1; char ch=0; while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar(); if(ch=='-')w=-1,ch=getchar(); while(ch>='0'&&ch<='9')data=((T)data<<3)+((T)data<<1)+(ch^'0'),ch=getchar(); x=data*w; } template<typename T> inline void write(T x,char c='\0') { if(x<0)putchar('-'),x=-x; if(x>9)write(x/10); putchar(x%10+'0'); if(c!='\0')putchar(c); } template<typename T> inline void chkmin(T &x,T y){x=(y<x?y:x);} template<typename T> inline void chkmax(T &x,T y){x=(y>x?y:x);} template<typename T> inline T min(T x,T y){return x<y?x:y;} template<typename T> inline T max(T x,T y){return x>y?x:y;} inline void init() { BIT.init(); for(register int i=1;i<=n;++i) { A1[i]=BIT.sum(n)-BIT.sum(A[i]); ans+=A1[i]; BIT.add(A[i],1); } BIT.init(); for(register int i=n;i>=1;--i) { A2[i]=BIT.sum(A[i]-1); BIT.add(A[i],1); } } int main() { read(n);read(m); for(register int i=1;i<=n;++i) { read(A[i]); pos[A[i]]=i; } init(); T.init(); while(m--) { write(ans,'\n'); int x; read(x); ans-=(A1[pos[x]]+A2[pos[x]]-T.sum(1,pos[x]-1,x,1)-T.sum(pos[x]+1,n,x,0)); T.add(pos[x],x); } return 0; }
【刷題】BZOJ 3295 [Cqoi2011]動態逆序對