您的位置:首页 > 其它

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

2015-06-03 21:28 483 查看
题意:每次询问区间(l,r)内的逆序对数

思路:莫队算法,利用树状数组进行查询更新

#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<vector>
#include<cmath>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<algorithm>
using namespace std;
const int maxn=50010;
typedef long long LL;

int N,M;
int size,cnt;
int a[maxn];
int X[maxn];
int pos[maxn];
int tree[maxn];

struct Q
{
    int l,r;
    int id;
    bool operator<(const Q &a)const
    {
        if((l-1)/size==(a.l-1)/size)return (r-1)/size<(a.r-1)/size;
        return (l-1)/size<(a.l-1)/size;
    }
}q[maxn];
LL ans[maxn];
void update(int x,int val)
{
    while(x<=cnt)
    {
        tree[x]+=val;
        x+=(x&(-x));
    }
}
int getsum(int x)
{
    int sum=0;
    while(x)
    {
        sum+=tree[x];
        x-=(x&(-x));
    }
    return sum;
}
int main()
{
    while(scanf("%d",&N)!=EOF)
    {
        for(int i=1;i<=N;i++)
        {
            scanf("%d",&a[i]);
            X[i]=a[i];
        }
        size=sqrt(N);
        sort(X+1,X+1+N);
        cnt=unique(X+1,X+1+N)-X-1;
        for(int i=1;i<=N;i++)
            pos[i]=lower_bound(X+1,X+cnt+1,a[i])-X;
        scanf("%d",&M);
        for(int i=1;i<=M;i++)
        {
            scanf("%d%d",&q[i].l,&q[i].r);
            q[i].id=i;
        }
        memset(tree,0,sizeof(tree));
        sort(q+1,q+1+M);
        int l=1,r=0;
        LL num=0;
        for(int i=1;i<=M;i++)
        {
            while(r<q[i].r)
            {
                num+=getsum(cnt)-getsum(pos[++r]);
                update(pos[r],1);
            }
            while(r>q[i].r)
            {
                num-=getsum(cnt)-getsum(pos[r]);
                update(pos[r--],-1);
            }
            while(l<q[i].l)
            {
                num-=getsum(pos[l]-1);
                update(pos[l++],-1);
            }
            while(l>q[i].l)
            {
                num+=getsum(pos[--l]-1);
                update(pos[l],1);
            }
            ans[q[i].id]=num;
        }
        for(int i=1;i<=M;i++)
            printf("%lld\n",ans[i]);
    }
    return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: