【bzoj3289】mato的文件管理

首先允许离线,一眼莫队……

然后考虑对于每次移动,这不就是让你求逆序对嘛(QAQ)

考虑怎么移动?

  1. 每次在最后添加一个数,比这个数大的数都会与其形成一个逆序对 
  2. 每次在最后移除一个数,比这个数大的数都会与其形成一个逆序对 
  3. 每次在最前添加一个数,比这个数小的数都会与其减少一个逆序对 
  4. 每次在最前移除一个数,比这个数小的数都会与其减少一个逆序对 

那么每次移动的时候我拿树状数组查询一下就好,注意要离散化。

 1 #include<bits/stdc++.h>
 2 #define N 50005
 3 #define inf 1000000007
 4 using namespace std;
 5 typedef unsigned int uint;
 6 uint ans[N],now;
 7 int n,m,a[N],b[N],rt[N];
 8 int c[20*N];
 9 struct Query{int l,r,id;}q[2*N];
10 inline int lowbit(int x){return x&(-x);}
11 bool operator<(Query x,Query y){
12     if(rt[x.l]==rt[y.l])return x.r<y.r;
13     return rt[x.l]<rt[y.l];
14 }
15 inline void add(int x,int val){
16     for(int i=x;i<=n;i+=lowbit(i))c[i]+=val;
17 }
18 uint ask(int x){
19     uint ans=0;
20     for(int i=x;i;i-=lowbit(i))ans+=c[i];
21     return ans;
22 }
23 inline int read(){
24     int f=1,x=0;char ch;
25     do{ch=getchar();if(ch=='-')f=-1;}while(ch<'0'||ch>'9');
26     do{x=x*10+ch-'0';ch=getchar();}while(ch>='0'&&ch<='9');
27     return f*x;
28 }
29 int main(){
30     n=read();int x=(int)sqrt(n);
31     for(int i=1;i<=n;i++)a[i]=read(),b[i]=a[i];
32     sort(b+1,b+n+1);
33     for(int i=1;i<=n;i++)a[i]=lower_bound(b+1,b+n+1,a[i])-b;
34     m=read();
35     for(int i=1;i<=m;i++)q[i].l=read(),q[i].r=read(),q[i].id=i;
36     for(int i=1;i<=n;i++)rt[i]=(i-1)/x+1;
37     sort(q+1,q+m+1);
38     int l=1,r=0;
39     for(int i=1;i<=m;i++){
40         while(l<q[i].l)add(a[l],-1),now-=ask(a[l]-1),l++;
41         while(r>q[i].r)add(a[r],-1),now-=r-l-ask(a[r]),r--;
42         while(l>q[i].l)l--,add(a[l],1),now+=ask(a[l]-1);
43         while(r<q[i].r)r++,add(a[r],1),now+=r-l+1-ask(a[r]);
44         ans[q[i].id]=now;
45     }
46     for(int i=1;i<=m;i++)printf("%d\n",ans[i]);
47     return 0;
48 }
View Code

 

posted @ 2017-05-12 21:24  zcysky  阅读(396)  评论(0编辑  收藏  举报