Bzoj3289 Mato的文件管理
Submit: 2272 Solved: 930
Description
Mato同学从各路神犇以各种方式(你们懂的)收集了许多资料,这些资料一共有n份,每份有一个大小和一个编号。为了防止他人偷拷,这些资料都是加密过的,只能用Mato自己写的程序才能访问。Mato每天随机选一个区间[l,r],他今天就看编号在此区间内的这些资料。Mato有一个习惯,他总是从文件大小从小到大看资料。他先把要看的文件按编号顺序依次拷贝出来,再用他写的排序程序给文件大小排序。排序程序可以在1单位时间内交换2个相邻的文件(因为加密需要,不能随机访问)。Mato想要使文件交换次数最小,你能告诉他每天需要交换多少次吗?
Input
第一行一个正整数n,表示Mato的资料份数。
第二行由空格隔开的n个正整数,第i个表示编号为i的资料的大小。
第三行一个正整数q,表示Mato会看几天资料。
之后q行每行两个正整数l、r,表示Mato这天看[l,r]区间的文件。
Output
q行,每行一个正整数,表示Mato这天需要交换的次数。
Sample Input
4
1 4 2 3
2
1 2
2 4
1 4 2 3
2
1 2
2 4
Sample Output
0
2
2
HINT
Hint
n,q <= 50000
样例解释:第一天,Mato不需要交换
第二天,Mato可以把2号交换2次移到最后。
Source
实际上是求一段区间的逆序对数。
莫队处理询问,树状数组求逆序对。
数据需要离散化,因为用了map,时间稍微慢了些,8000+ms
1 /*by SilverN*/ 2 #include<algorithm> 3 #include<iostream> 4 #include<cstring> 5 #include<cstdio> 6 #include<cmath> 7 #include<map> 8 #define LL long long 9 using namespace std; 10 const int mxn=100010; 11 int read(){ 12 int x=0,f=1;char ch=getchar(); 13 while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();} 14 while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();} 15 return x*f; 16 } 17 LL t[mxn]; 18 int n,T; 19 map<int,int>mp; 20 void add(int x,int v){ 21 while(x<=n){t[x]+=v;x+=x&-x;} 22 return; 23 } 24 LL smm(int x){ 25 LL res=0; 26 while(x){res+=t[x];x-=x&-x;} 27 return res; 28 } 29 // 30 struct que{ 31 int l,r; 32 int id; 33 int m; 34 }q[mxn]; 35 int cmp(que a,que b){ 36 if(a.m!=b.m)return a.m<b.m; 37 return a.r<b.r; 38 } 39 int a[mxn]; 40 LL ans[mxn]; 41 // 42 void solve(){ 43 int i,j; 44 int l=1,r=0; 45 LL tmp=0; 46 for(i=1;i<=T;i++){ 47 while(l<q[i].l){ 48 add(a[l],-1); 49 tmp-=smm(a[l]-1); 50 ++l; 51 } 52 while(r>q[i].r){ 53 add(a[r],-1); 54 tmp-=(smm(n)-smm(a[r])); 55 --r; 56 } 57 while(l>q[i].l){ 58 l--; 59 add(a[l],1); 60 tmp+=smm(a[l]-1); 61 } 62 while(r<q[i].r){ 63 r++; 64 add(a[r],1); 65 tmp+=(smm(n)-smm(a[r])); 66 } 67 ans[q[i].id]=tmp; 68 } 69 return; 70 } 71 int bas[mxn]; 72 int main(){ 73 n=read(); 74 int i,j; 75 for(i=1;i<=n;++i)a[i]=read(); 76 memcpy(bas,a,sizeof a); 77 sort(bas+1,bas+n+1); 78 for(i=1;i<=n;++i)if(!mp[bas[i]])mp[bas[i]]=i; 79 for(i=1;i<=n;++i)a[i]=mp[a[i]]; 80 int block=sqrt(n); 81 T=read(); 82 for(i=1;i<=T;++i){ 83 q[i].id=i; 84 q[i].l=read();q[i].r=read(); 85 q[i].m=(q[i].l-1)/block+1; 86 } 87 sort(q+1,q+T+1,cmp); 88 // printf("fin1\n"); 89 solve(); 90 // printf("fin2\n"); 91 for(i=1;i<=T;i++){ 92 printf("%lld\n",ans[i]); 93 } 94 return 0; 95 }
本文为博主原创文章,转载请注明出处。