bzoj3289: Mato的文件管理

莫队算法+树状数组+离散化。

一定要注意莫队转移时增加或减少的逆序对数,比较容易写挂。

离散化那部分虽然效率很低,但是很好写,正确性也很容易保证,虽然会拖慢程序运行速度,但编码的复杂度却大大降低了。

我觉得是一种不错的选择。//反正是抄的黄学长的。。

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
const int maxn = 50000 + 10;
int pos[maxn],a[maxn],n,m,block,l,r,ans,res[maxn];
int disc[maxn];

struct data {
    int l,r,id;
}q[maxn];

bool cmp(data a,data b) {
    if(pos[a.l]==pos[b.l]) return a.r<b.r;
    return a.l<b.l;
}

struct BIT {
    int a[maxn];
    
    inline int lowbit(int x) {
        return x&-x;
    }
    
    void add(int x,int val) {
        for(int i=x;i<=n;i+=lowbit(i))
            a[i]+=val;    
    }
    
    int query(int x) {
        int res=0;
        for(int i=x;i;i-=lowbit(i)) 
            res+=a[i];
        return res;    
    }
}bit;

int main() {
    scanf("%d",&n);
    for(int i=1;i<=n;i++) {
        scanf("%d",&a[i]);
        disc[i]=a[i];
    }
    sort(disc+1,disc+n+1);
    for(int i=1;i<=n;i++) a[i]=lower_bound(disc+1,disc+n+1,a[i])-disc;
    scanf("%d",&m);
    for(int i=1;i<=m;i++) {
        scanf("%d%d",&q[i].l,&q[i].r);
        q[i].id=i;
    }
    block = (int) sqrt(n+0.5);
    for(int i=1;i<=n;i++) pos[i]=(i-1)/block+1;
    sort(q+1,q+m+1,cmp);
    l=1,r=0,ans=0;
    for(int i=1;i<=m;i++) {
        while(r<q[i].r) {
            r++;
            bit.add(a[r],1);
            ans+=r-l+1-bit.query(a[r]);
        }
        while(l<q[i].l) {
            bit.add(a[l],-1);
            ans-=bit.query(a[l]);
            l++;
        }
        while(l>q[i].l) {
            l--;
            ans+=bit.query(a[l]);
            bit.add(a[l],1);    
        }
        while(r>q[i].r) {
            bit.add(a[r],-1);
            ans-=r-l-bit.query(a[r]);
            r--;
        }
        res[q[i].id]=ans;
    }
    for(int i=1;i<=m;i++) printf("%d\n",res[i]);
    return 0;
}
posted @ 2016-06-01 19:47  invoid  阅读(137)  评论(0编辑  收藏  举报