HYSBZ - 3289 Mato的文件管理 莫队算法+树状数组
作者:互联网
题目链接:https://cn.vjudge.net/problem/HYSBZ-3289
Mato同学从各路神犇以各种方式(你们懂的)收集了许多资料,这些资料一共有n份,每份有一个大小和一个编号
。为了防止他人偷拷,这些资料都是加密过的,只能用Mato自己写的程序才能访问。Mato每天随机选一个区间[l,r
],他今天就看编号在此区间内的这些资料。Mato有一个习惯,他总是从文件大小从小到大看资料。他先把要看的
文件按编号顺序依次拷贝出来,再用他写的排序程序给文件大小排序。排序程序可以在1单位时间内交换2个相邻的
文件(因为加密需要,不能随机访问)。Mato想要使文件交换次数最小,你能告诉他每天需要交换多少次吗?
Input
第一行一个正整数n,表示Mato的资料份数。
第二行由空格隔开的n个正整数,第i个表示编号为i的资料的大小。
第三行一个正整数q,表示Mato会看几天资料。
之后q行每行两个正整数l、r,表示Mato这天看[l,r]区间的文件。
n,q <= 50000
Output
q行,每行一个正整数,表示Mato这天需要交换的次数。
Sample Input
4 1 4 2 3 2 1 2 2 4
Sample Output
0 2 //样例解释:第一天,Mato不需要交换 第二天,Mato可以把2号交换2次移到最后。
题解:左边操作的时候,查询比他大的,右边操作的时候,查询比他小的,注意要离散化一下。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define lowbit(x) x&(-x)
const int N=50010;
struct node{
int l,r;
int id;
}a[N];
int n,m,CM;
int c[N],b[N];
int sum1[N];// xiao
int sum2[N];// da
ll ans[N];
bool cmp(node x,node y)
{
if(x.l/CM!=y.l/CM) return x.l<y.l;
else return x.r<y.r;
}
void update1(int x,int val)
{
while(x<=n)
{
sum1[x]+=val;
x+=lowbit(x);
}
}
int query1(int x)
{
int res=0;
while(x)
{
res+=sum1[x];
x-=lowbit(x);
}
return res;
}
void update2(int x,int val)
{
while(x)
{
sum2[x]+=val;
x-=lowbit(x);
}
}
int query2(int x)
{
int res=0;
while(x<=n)
{
res+=sum2[x];
x+=lowbit(x);
}
return res;
}
int main()
{
while(scanf("%d",&n)!=EOF)
{
// scanf("%d",&n);
for(int i=1;i<=n;i++)scanf("%d",&c[i]),b[i]=c[i];
sort(b+1,b+1+n);
int len=unique(b+1,b+1+n)-(b+1);
CM=(int)sqrt(n);
for(int i=1;i<=n;i++)
{
c[i]=lower_bound(b+1,b+1+len,c[i])-b;
}
scanf("%d",&m);
for(int i=1;i<=m;i++)scanf("%d%d",&a[i].l,&a[i].r),a[i].id=i;
sort(a+1,a+1+m,cmp);
int l,r;
ll res;
for(int i=1,j=1;j<=m;i++)
{
memset(sum1,0,sizeof(sum1));
memset(sum2,0,sizeof(sum2));
l=a[j].l+1,r=a[j].l;
res=0;
for(;j<i*CM && j<=m;j++)
{
while(a[j].l<l)
{
l--;
res+=query1(c[l]-1);
update1(c[l],1);
update2(c[l],1);
}
while(a[j].l>l)
{
res-=query1(c[l]-1);
update1(c[l],-1);
update2(c[l],-1);
l++;
}
while(a[j].r<r)
{
res-=query2(c[r]+1);
update1(c[r],-1);
update2(c[r],-1);
r--;
}
while(a[j].r>r)
{
r++;
res+=query2(c[r]+1);
update1(c[r],1);
update2(c[r],1);
}
ans[a[j].id]=res;
l=a[j].l,r=a[j].r;
}
}
for(int i=1;i<=m;i++)
{
printf("%lld\n",ans[i]);
}
}
return 0;
}
标签:正整数,int,HYSBZ,ll,交换,3289,资料,Mato 来源: https://blog.csdn.net/mmk27_word/article/details/90209859