【分块】bzoj3295 [Cqoi2011]动态逆序对
考虑每次删除pos位置一个数x后,所造成的的影响就是,逆序对的个数少了在1~pos-1中大于x的数的个数加上pos+1~n中小于x的数的个数。
那么我们需要的操作就只有查询区间内比某数大(小)的个数。
↑,分块经典操作,每个块里维护一个有序表。
由于有删除,最好每个块用一个vector。
对于原数列怎么办呢?只需要弄一个vis数组,vis[i]表示i位置的数已经删除即可。(要找到v在原数列中的位置的话,在其所在块暴力即可。)
查询时对整块二分,对要删的元素所在块分成两段暴力。
O(n*sqrt(n)*log2(sqrt(n)))
【觉得我已经丧心病狂了,bzoj的树套树题只会用分块水怎么办啊,一旦不是总时限不就T了吗……QAQ】
P.S.请用long long。
1 #include<cstdio> 2 #include<vector> 3 #include<algorithm> 4 #include<cmath> 5 using namespace std; 6 bool vis[100001]; 7 int n,m,a[100001],sum,num[100001],sz,l[400],r[400],v; 8 long long ans; 9 vector<int>b[400]; 10 vector<int>::iterator it; 11 int Res,Num;char C,CH[12]; 12 inline int G() 13 { 14 Res=0;C='*'; 15 while(C<'0'||C>'9')C=getchar(); 16 while(C>='0'&&C<='9'){Res=Res*10+(C-'0');C=getchar();} 17 return Res; 18 } 19 inline void P(long long x) 20 { 21 Num=0;if(!x){putchar('0');puts("");return;} 22 while(x>0)CH[++Num]=x%10,x/=10; 23 while(Num)putchar(CH[Num--]+48); 24 puts(""); 25 } 26 void makeblock() 27 { 28 sz=sqrt((double)n*log2(n)); 29 for(sum=1;sum*sz<n;sum++) 30 { 31 l[sum]=(sum-1)*sz+1; 32 r[sum]=sum*sz; 33 for(int i=l[sum];i<=r[sum];i++) num[i]=sum,b[sum].push_back(a[i]); 34 sort(b[sum].begin(),b[sum].end()); 35 } 36 l[sum]=sz*(sum-1)+1; r[sum]=n; 37 for(int i=l[sum];i<=r[sum];i++) {num[i]=sum; b[sum].push_back(a[i]);} 38 sort(b[sum].begin(),b[sum].end()); 39 } 40 int D[100001];inline int lowbit(const int &x){return x&(-x);} 41 inline int getsum(int x){int res=0;while(x>0){res+=D[x];x-=lowbit(x);}return res;} 42 inline void add(int x,const int &d){while(x<=n){D[x]+=d;x+=lowbit(x);}} 43 void Get_First_Ans() 44 {for(int i=1;i<=n;i++){add(a[i],1);ans+=(long long)i-getsum(a[i]);}} 45 int Get_Pos(const int &v,const int &L,const int &R) 46 {for(int i=L;i<=R;i++) if(!vis[i] && a[i]==v) return i;} 47 void update() 48 { 49 for(int i=1;i<=sum;i++) 50 { 51 it=lower_bound(b[i].begin(),b[i].end(),v); 52 if(*it==v) 53 { 54 int p=Get_Pos(v,l[i],r[i]); vis[p]=true; 55 for(int j=1;j<i;j++) ans-=(long long)(b[j].end()-upper_bound(b[j].begin(),b[j].end(),v)); 56 for(int j=l[i];j<p;j++) if(!vis[j] && a[j]>v) ans--; 57 for(int j=i+1;j<=sum;j++) ans-=(long long)(lower_bound(b[j].begin(),b[j].end(),v)-b[j].begin()); 58 for(int j=p+1;j<=r[i];j++) if(!vis[j] && a[j]<v) ans--; 59 b[i].erase(it); 60 break; 61 } 62 } 63 } 64 int main() 65 { 66 n=G();m=G(); 67 for(int i=1;i<=n;i++) a[i]=G(); 68 Get_First_Ans(); 69 makeblock(); 70 for(int i=1;i<=m;i++) 71 { 72 v=G(); P(ans); 73 update(); 74 } 75 return 0; 76 }
——The Solution By AutSky_JadeK From UESTC
转载请注明出处:http://www.cnblogs.com/autsky-jadek/