[bozj3289]Mato的文件管理

莫队裸题。。

开个树状数组,跟维护逆序对一模一样(动态逆序对?由于只有边界上的点加减,应该算作伪动态逆序对。)。。

然后记得离散化一下。。不然就炸了。。

(似乎不会有重复的数字吧。。)

(似乎开平衡树的话也能跑。。然而平衡树写挂了。。。开平衡树唯一好的地方就是不需要离散化了。。不过没什么用。。)

 1 #include <iostream>
 2 #include <algorithm>
 3 #include <cstring>
 4 #include <cstdlib>
 5 #include <map>
 6 #include <string>
 7 #include <vector>
 8 #include <stack>
 9 #include <cmath>
10 #include <queue>
11 #include <cstdio>
12 #include <set>
13 using namespace std;
14 
15 const int N=600000;
16 struct ASK{
17     int l,r,id,ans,bl;
18     bool operator<(ASK b)const{
19         if(bl==b.bl)return r<b.r;
20         return bl<b.bl;
21     }
22 }bs[N];
23 bool cmp(ASK a,ASK b){return a.id<b.id;}
24 int n,q,a[N],b[N],l=1,r,v[N],now;
25 void add(int i,int vv){
26     for(;i<=n;i+=i&-i)v[i]+=vv;
27 }
28 int ask(int i,int ret=0){
29     for(;i;i-=i&-i)ret+=v[i];
30     return ret;
31 }
32 int main(){
33     scanf("%d",&n);
34     for(int i=1;i<=n;i++)scanf("%d",&a[i]),b[i]=a[i];
35     sort(b+1,b+1+n);
36     for(int i=1;i<=n;i++)a[i]=lower_bound(b+1,b+1+n,a[i])-b;
37     scanf("%d",&q);
38     for(int i=1;i<=q;i++)scanf("%d%d",&bs[i].l,&bs[i].r),bs[i].id=i,bs[i].bl=bs[i].l/sqrt(n);
39     sort(bs+1,bs+1+q);
40     for(int i=1;i<=q;i++){
41         while(r<bs[i].r){
42             add(a[++r],1);
43             now+=r-l+1-ask(a[r]);
44         }
45         while(r>bs[i].r){
46             add(a[r],-1);
47             now-=r-l-ask(a[r]);
48             r--;
49         }
50         while(l<bs[i].l){
51             add(a[l],-1);
52             now-=ask(a[l]-1);
53             l++;
54         }
55         while(l>bs[i].l){
56             l--;
57             add(a[l],1);
58             now+=ask(a[l]-1);
59         }
60         bs[i].ans=now;
61     }
62     sort(bs+1,bs+1+q,cmp);
63     for(int i=1;i<=q;i++)printf("%d\n",bs[i].ans);
64 }
View Code

 

posted @ 2017-01-04 21:21  KingSann  阅读(171)  评论(0编辑  收藏  举报