【分块】【树套树】bzoj2141 排队

考虑暴力更新的情况,设swap的是L,R位置的数。
swap之后的逆序对数应该等于:
之前的逆序对数
+[L+1,R-1]中比 L位置的数 大的数的个数
-[L+1,R-1]中比 L位置的数 小的数的个数
-[L+1,R-1]中比 R位置的数 大的数的个数
+[L+1,R-1]中比 R位置的数 小的数的个数

并且若L位置的数>R位置的数,逆序对数--;反之,逆序对数++。

分块,对每个块内部进行sort,这样可以二分,在O(log(sqrt(n))的时间内求得某个块内比某个数大/小的数的个数。所以每次更新是O(sqrt(n)*log(sqrt(n))的。
若L和R所在的块相同或相邻时,直接暴力更新即可。

要用树状数组或归并排序求得初始答案。

要注意数据是可重的,所以要打时间戳。
所以为了lower_bound/upper_bound,要定义两套比较法则,一套双关键字,一套单关键字。

 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<cmath>
 4 using namespace std;
 5 struct Point{int v,p;Point(const int &a,const int &b){v=a;p=b;}Point(){}};
 6 bool operator < (const Point &a,const Point &b){return a.v<b.v;}//单关键字比较 
 7 bool operator > (const Point &a,const Point &b){return a.v>b.v;}
 8 bool operator == (const Point &a,const Point &b){return a.v==b.v ? true : false;}
 9 bool cmp(const Point &a,const Point &b){return a.v!=b.v ? a.v<b.v : a.p<b.p;}//双关键字比较 
10 Point b[20001],a[20001],c[20001];
11 int n,sz,l[145],r[145],sum,num[20001],ans,x,y,m,mid,en;
12 int Res,Num;char C,CH[20];
13 inline int G()
14 {
15     Res=0;C='*'; 
16     while(C<'0'||C>'9')C=getchar();
17     while(C>='0'&&C<='9'){Res=Res*10+(C-'0');C=getchar();}
18     return Res;
19 }
20 inline void P(int x)
21 {
22     if(!x){putchar('0');putchar('\n');return;}
23     Num=0;while(x>0)CH[++Num]=x%10,x/=10;
24     while(Num)putchar(CH[Num--]+48);
25     putchar('\n');
26 }
27 void LiSan()
28 {
29     n=G();
30     for(int i=1;i<=n;i++){b[i].v=G();b[i].p=i;}
31     sort(b+1,b+n+1,cmp);
32     for(int i=1;i<=n;i++)
33       {
34           if(b[i].v!=b[i-1].v)en++;
35         a[b[i].p].v=en;
36         a[b[i].p].p=i;
37       }
38 }
39 //树状数组求出初始答案。 
40 int D[20001];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].v,1);ans+=(i-getsum(a[i].v));}
45 P(ans);}
46 void makeblock()
47 {
48     sz=sqrt(n);
49     for(sum=1;sum*sz<n;sum++)
50       {
51         l[sum]=(sum-1)*sz+1;r[sum]=sum*sz;
52           for(int i=l[sum];i<=r[sum];i++)
53           num[i]=sum;
54       }
55     l[sum]=sz*(sum-1)+1;r[sum]=n;
56     for(int i=l[sum];i<=r[sum];i++)
57       num[i]=sum;
58 }
59 void Sort_Each_Block()
60 {for(int i=1;i<=n;i++)c[i]=a[i];
61 for(int i=1;i<=sum;i++)sort(a+l[i],a+r[i]+1,cmp);}
62 inline int Query(const int &L,const int &R)
63 {
64     swap( a[lower_bound(a+l[num[L]],a+r[num[L]]+1,c[L],cmp) - a ]
65     , a[lower_bound(a+l[num[R]],a+r[num[R]]+1,c[R],cmp)- a ]);//必须双关键字比较 
66     sort(a+l[num[L]],a+r[num[L]]+1,cmp);
67     sort(a+l[num[R]],a+r[num[R]]+1,cmp);
68     int cnt=0;
69     if(c[L].v<c[R].v)cnt=1;
70     else if(c[L].v>c[R].v)cnt=-1;
71     swap(c[L],c[R]);
72     if(num[L]+1>=num[R])
73       for(int i=L+1;i<=R-1;i++)
74           {if(c[i].v>c[R].v)cnt++;else if(c[i].v<c[R].v)cnt--;
75            if(c[i].v>c[L].v)cnt--;else if(c[i].v<c[L].v)cnt++;}
76     else
77       {
78           for(int i=L+1;i<=r[num[L]];i++)
79             {if(c[i].v>c[R].v)cnt++;else if(c[i].v<c[R].v)cnt--;
80              if(c[i].v>c[L].v)cnt--;else if(c[i].v<c[L].v)cnt++;}
81           for(int i=l[num[R]];i<=R-1;i++)
82             {if(c[i].v>c[R].v)cnt++;else if(c[i].v<c[R].v)cnt--;
83              if(c[i].v>c[L].v)cnt--;else if(c[i].v<c[L].v)cnt++;}
84           for(int i=num[L]+1;i<=num[R]-1;i++)
85             {
86                 cnt+=( (a+r[i]+1) - upper_bound(a+l[i],a+r[i]+1,c[R]) );//必须单关键字比较 
87                 cnt-=( lower_bound(a+l[i],a+r[i]+1,c[R]) - (a+l[i]) );
88             cnt-=( (a+r[i]+1) - upper_bound(a+l[i],a+r[i]+1,c[L]) );
89             cnt+=( lower_bound(a+l[i],a+r[i]+1,c[L]) - (a+l[i]) );
90             }
91       }
92     ans+=cnt;return ans;
93 }
94 int main()
95 {
96     LiSan();Get_First_Ans();makeblock();Sort_Each_Block();m=G();
97     for(int i=1;i<=m;i++){x=G();y=G();if(x>y)swap(x,y);P(Query(x,y));}
98     return 0;
99 }

 

posted @ 2014-09-12 15:21  AutSky_JadeK  阅读(210)  评论(0编辑  收藏  举报
TVアニメ「Charlotte(シャーロット)」公式サイト TVアニメ「Charlotte(シャーロット)」公式サイト