您的位置:首页 > 其它

bzoj 3289 Mato的文件管理(莫队算法+BIT)

2016-04-01 14:52 531 查看
【题目链接】

http://www.lydsy.com/JudgeOnline/problem.php?id=3289

【题意】

回答若干个询问:[l,r]区间内的逆序对个数。

【思路】

莫队算法,BIT维护插入删除。

使用BIT维护当前指针l,r内的所有的数。考虑转移部分:

l<q[i].l 删出区间中比a[l]小的数与之构成的逆序对,Q(a[l]-1)

l>q[i].l l++,添加区间中比a[l]小的数与之构成的逆序对,Q(a[l]-1)

r>q[i].r 删除区间中比a[r]大的数与之构成的逆序对,r-l+1-Q(a[r])

r<q[i].r r++,添加区间中比a[r]大的数与之构成的逆序对,r-l-Q(a[r])

相应修改BIT。

这一部分比较容易出错 =_=

【代码】

#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define FOR(a,b,c) for(int a=b;a<=c;a++)
using namespace std;

typedef long long ll;
const int N = 1e5+10;

ll read() {
char c=getchar();
ll f=1,x=0;
while(!isdigit(c)) {
if(c=='-') f=-1; c=getchar();
}
while(isdigit(c))
x=x*10+c-'0',c=getchar();
return x*f;
}

struct Node {
int pos,id,l,r;
bool operator < (const Node& rhs) const
{
return pos<rhs.pos||(pos==rhs.pos&&r<rhs.r);
}
} q
;

int n,m;
int C
,a
,hash
,tot;
ll ans
;

void add(int x,int v)
{
for(;x<=tot;x+=x&-x) C[x]+=v;
}
ll query(int x)
{
ll sum=0;
for(;x;x-=x&-x) sum+=(ll)C[x];
return sum;
}

int main()
{
n=read();
FOR(i,1,n) a[i]=read(),hash[++tot]=a[i];
sort(hash+1,hash+n+1);
tot=unique(hash+1,hash+n+1)-hash-1;
FOR(i,1,n) a[i]=lower_bound(hash+1,hash+n+1,a[i])-hash;

m=read();
int B=sqrt(n);
FOR(i,1,m)
{
q[i].l=read(),
q[i].r=read();
q[i].id=i;
q[i].pos=(q[i].l-1)/B+1;
}
sort(q+1,q+m+1);

ll now=0;
int l=1,r=0;
FOR(i,1,m)
{
while(l<q[i].l)
now-=query(a[l]-1),add(a[l],-1),l++;
while(l>q[i].l)
l--,now+=query(a[l]-1),add(a[l],1);
while(r>q[i].r)
now-=r-l+1-query(a[r]),add(a[r],-1),r--;
while(r<q[i].r)
r++,now+=r-l-query(a[r]),add(a[r],1);
ans[q[i].id]=now;
}

FOR(i,1,m)
printf("%lld\n",ans[i]);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: