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

来源:互联网 发布:石油期货模拟软件 编辑:程序博客网 时间:2024/05/05 12:07

题目链接:bzoj-3289-Mato的文件管理

最大交换次数应该是区间的逆序对数,每次交换消除一个逆序对(不会证明)。
求逆序对可以用树状数组来实现。每次转移是 O(logn) 的。
因此总复杂度是 O(n32logn)

#include<bits/stdc++.h>using namespace std;typedef long long ll;const int maxn=55000;int c[maxn],d[maxn],pos[maxn];int a[maxn];int n,L,R,m;ll Ans,ans[maxn];struct Query{    int l,r,id;    bool operator < (const Query & b) const    {        return pos[l]<pos[b.l]||(pos[l]==pos[b.l]&&r<b.r);    }}Q[maxn];inline int lowbit(int x){    return x&-x;}inline void modify(int x,int k){    for(;x<maxn;x+=lowbit(x))        c[x]+=k;}inline int sum(int x){    int res=0;    for(;x>0;x-=lowbit(x))        res+=c[x];    return res;}int main(){    while(~scanf("%d",&n))    {        int sz=sqrt(n);        for(int i=1;i<=n;i++)        {            scanf("%d",&a[i]);            d[i]=a[i];            pos[i]=i/sz;        }        sort(d+1,d+n+1);        for(int i=1;i<=n;i++)            a[i]=lower_bound(d+1,d+n+1,a[i])-d;        scanf("%d",&m);        for(int i=1;i<=m;i++)        {            cin>>Q[i].l>>Q[i].r;            Q[i].id=i;        }        sort(Q+1,Q+1+m);        L=1;R=0;Ans=0;        memset(c,0,sizeof(c));        for(int i=1;i<=m;i++)        {            while(R<Q[i].r)            {                ++R;                modify(a[R],1);                Ans+=R-L+1-sum(a[R]);            }            while(R>Q[i].r)            {                modify(a[R],-1);                Ans-=R-L-sum(a[R]);                --R;            }            while(L<Q[i].l)            {                modify(a[L],-1);                Ans-=sum(a[L]);                ++L;            }            while(L>Q[i].l)            {                --L;                modify(a[L],1);                Ans+=sum(a[L]-1);            }            if(Q[i].id>=maxn) while(1);            ans[Q[i].id]=Ans;        }        for(int i=1;i<=m;i++)            printf("%lld\n",ans[i]);    }    return 0;}
0 0
原创粉丝点击