现在的位置: 首页 > 综合 > 正文

BZOJ 3289 Mato的文件管理 莫队算法+树状数组

2017年05月02日 ⁄ 综合 ⁄ 共 1227字 ⁄ 字号 评论关闭

题目大意:给定一个序列,多次询问区间内逆序对的数量

总算是明白城市旅行是如何RE的了……尼玛BZOJ坑爹 ostream输出流过大居然会RE!输出时顺手用了cout结果各种RE不止……原来是这样

建议各位在死活RE就是找不到原因的时候检查一下是否大输出用了cout

这题用莫队可以很简单搞掉 逆序对用树状数组就可以维护 一会去想想强制在线怎么搞

#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define M 50500
using namespace std;
struct abcd{
	int l,r,pos;
	bool operator < (const abcd x) const;
}q[M];
int n,m,l=1,r=0,tot,block,a[M],c[M];
pair<int,int>b[M];
long long now,ans[M];
bool abcd :: operator < (const abcd x) const
{
	if( (l-1)/block == (x.l-1)/block )
		return r < x.r;
	return (l-1)/block < (x.l-1)/block;
}
void Update(int x,int y)
{
	for(;x<=tot;x+=x&-x)
		c[x]+=y;
}
int Get_Ans(int x)
{
	int re=0;
	for(;x;x-=x&-x)
		re+=c[x];
	return re;
}
int main()
{
	int i;
	cin>>n;
	for(i=1;i<=n;i++)
		scanf("%d",&b[i].first),b[i].second=i;
	sort(b+1,b+n+1);
	for(i=1;i<=n;i++)
	{
		if(i==1||b[i].first!=b[i-1].first)
			++tot;
		a[b[i].second]=tot;
	}
	block=(int)ceil(sqrt(n));
	cin>>m;
	for(i=1;i<=m;i++)
		scanf("%d%d",&q[i].l,&q[i].r),q[i].pos=i;
	sort(q+1,q+m+1);
	for(i=1;i<=m;i++)
	{
		while(l>q[i].l)
			now+=Get_Ans(a[--l]-1),Update(a[l],1);
		while(r<q[i].r)
			now+=Get_Ans(tot)-Get_Ans(a[++r]),Update(a[r],1);
		while(l<q[i].l)
			Update(a[l],-1),now-=Get_Ans(a[l++]-1);
		while(r>q[i].r)
			Update(a[r],-1),now-=Get_Ans(tot)-Get_Ans(a[r--]);
		ans[q[i].pos]=now;
	}
	for(i=1;i<=m;i++)
		printf("%lld\n",ans[i]);
}

抱歉!评论已关闭.