BZOJ3289: Mato的文件管理

$n \leq 50000$,$q \leq 50000$,$n$的数列$q$个询问,每次问某个区间只交换相邻俩数,要交换几次才能升序。数字范围不知反正要离散化。

注意不要学了莫队就把离线题套路忘了,询问右端点排序也是常用快捷方法。

好那我们试试。不会。好上莫队。

每次增加一个数,答案加上比他大(在右边加入)或比他小(在左边加入)的数。上树状数组。

 1 //#include<iostream>
 2 #include<cstring>
 3 #include<cstdlib>
 4 #include<cstdio>
 5 //#include<queue>
 6 //#include<time.h>
 7 //#include<complex>
 8 #include<algorithm>
 9 #include<stdlib.h>
10 using namespace std;
11 
12 int n,m,tot,lq;
13 #define maxn 50011
14 int a[maxn],bel[maxn];
15 struct Ques{int l,r,id;}q[maxn];
16 bool cmp(const Ques a,const Ques b) {return bel[a.l]==bel[b.l]?a.r<b.r:a.l<b.l;}
17 
18 int lisa[maxn],li,ans[maxn],ss;
19 struct BIT
20 {
21     int a[maxn],n;
22     void clear(int m) {n=m;}
23     void add(int x,int v) {for (;x<=n;x+=x&-x) a[x]+=v;}
24     int query(int x) {int ans=0; for (;x;x-=x&-x) ans+=a[x]; return ans;}
25 }t;
26 void modifyl(int x,int type) {ss+=type*t.query(a[x]-1); t.add(a[x],type);}
27 void modifyr(int x,int type) {ss+=type*(t.query(t.n)-t.query(a[x])); t.add(a[x],type);}
28 
29 int main()
30 {
31     scanf("%d",&n); m=233;
32     for (int i=1;i<=n;i++) bel[i]=(i-1)/m+1; tot=bel[n];
33     for (int i=1;i<=n;i++) scanf("%d",&a[i]),lisa[++li]=a[i];
34     sort(lisa+1,lisa+1+li); li=unique(lisa+1,lisa+1+li)-lisa-1;
35     for (int i=1;i<=n;i++) a[i]=lower_bound(lisa+1,lisa+1+li,a[i])-lisa;
36     t.clear(li);
37     
38     scanf("%d",&lq);
39     for (int i=1;i<=lq;i++) scanf("%d%d",&q[i].l,&q[q[i].id=i].r);
40     sort(q+1,q+1+lq,cmp);
41     int L=1,R=0; ss=0;
42     for (int i=1;i<=lq;i++)
43     {
44         while (L<q[i].l) modifyl(L,-1),L++;
45         while (L>q[i].l) L--,modifyl(L,1);
46         while (R<q[i].r) R++,modifyr(R,1);
47         while (R>q[i].r) modifyr(R,-1),R--;
48         ans[q[i].id]=ss;
49     }
50     for (int i=1;i<=lq;i++) printf("%d\n",ans[i]);
51     return 0;
52 }
View Code

 

posted @ 2018-03-15 11:01  Blue233333  阅读(132)  评论(0编辑  收藏  举报