码迷,mamicode.com
首页 > 其他好文 > 详细

【分块】bzoj3295 [Cqoi2011]动态逆序对

时间:2014-10-16 20:36:13      阅读:214      评论:0      收藏:0      [点我收藏+]

标签:style   blog   color   io   os   ar   for   sp   div   

考虑每次删除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 }

 

【分块】bzoj3295 [Cqoi2011]动态逆序对

标签:style   blog   color   io   os   ar   for   sp   div   

原文地址:http://www.cnblogs.com/autsky-jadek/p/4029339.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!