hdu 5196 DZY Loves Inversions(线段树+树状数组+离线+two points)

来源:互联网 发布:java 字符串的分割 编辑:程序博客网 时间:2024/06/04 01:04

先离散化数组,定义了两个数组r[i]和r1[i],r[i]表示min{ j( j~i的逆序数对小于等于k)},r1[i]表示min{ j( j~i的逆序数对小于k)},然后离线处理查询,接着从1开始遍历每个位置,假如遍历到i如果r[i]<r1[i] 那就在r[i]~r1[i]-1每个位置加1(lazy),加完之后遍历以i结尾的查询(也就是l~r 其中r=i)那么这个查询的值就是l~r每个位置加的数之和.

有个超级大坑点就是1个数的逆序数对也为0,所以k=0的时候一定要考虑到这点(wa了一上午)。


#include<cstdio>#include<cstring>#include<algorithm>#include<iostream>#include<vector>using namespace std;const int maxn=100005;typedef long long LL;int bit[maxn];struct ppi{    int id;    int to;}pp1;vector<ppi >g[maxn];int low(int p){return p&(-p);}void merg(int p,int n,int k){    while(p<=n){        bit[p]+=k;        p=p+low(p);    }}int sum(int p){    int s=0;    while(p>0){        s+=bit[p];        p=p-low(p);    }    return s;}int r[maxn],r1[maxn];int a[maxn],b[maxn];LL c[maxn];struct pi{    int le;    int ri;    int lazy;    LL sum;}pp[maxn<<2];void build(int tot,int l,int r){    pp[tot].le=l;    pp[tot].ri=r;    pp[tot].sum=0;    pp[tot].lazy=0;    if(l==r) return ;    build(2*tot,l,(l+r)/2);    build(2*tot+1,(l+r)/2+1,r);}void merg1(int tot,int l,int r,int p){    if(pp[tot].le>=l&&pp[tot].ri<=r){        pp[tot].lazy+=p;        return ;    }    int mid=(pp[tot].le+pp[tot].ri)/2;    if(l<=mid) merg1(2*tot,l,r,p);    if(r>mid) merg1(2*tot+1,l,r,p);    pp[tot].sum+=(min(r,pp[tot].ri)-max(l,pp[tot].le)+1)*p;}LL sum(int tot,int l,int r){    if(pp[tot].le>=l&&pp[tot].ri<=r){        return (LL)(pp[tot].ri-pp[tot].le+1)*(pp[tot].lazy)+pp[tot].sum;    }    LL s=0;    int mid=(pp[tot].le+pp[tot].ri)/2;    s=(LL)(min(r,pp[tot].ri)-max(l,pp[tot].le)+1)*pp[tot].lazy;    if(l<=mid) s+=sum(2*tot,l,r);    if(r>mid) s+=sum(2*tot+1,l,r);    return s;}int main(){    int i,j,n,m;    LL k,k1;    while(scanf("%d%d%I64d",&n,&m,&k)!=EOF){        memset(bit,0,sizeof(bit));        for(i=1;i<=n;i++){            scanf("%d",&b[i]);            a[i]=b[i];        }        sort(b+1,b+1+n);        for(i=1;i<=n;i++){            a[i]=(int)(lower_bound(b+1,b+1+n,a[i])-b);        }        j=1;        k1=0;        r[1]=1;        merg(a[1],n,1);        for(i=2;i<=n;i++){            while(j<=i){                int p=sum(n)-sum(a[i]);                if(k<p+k1){                    int w=sum(a[j]-1);                    k1-=w;                    merg(a[j],n,-1);                    j++;                }                else{                    k1=p+k1;                    break;                }            }            merg(a[i],n,1);            r[i]=j;            if(j>i){                r[i]=i;            }        }        if(k==0){            for(j=1;j<=n;j++){                r1[j]=j+1;            }        }        else{            j=1;            k1=0;            r1[1]=1;            memset(bit,0,sizeof(bit));            merg(a[1],n,1);            for(i=2;i<=n;i++){                while(j<=i){                    int p=sum(n)-sum(a[i]);                    if(k<=p+k1){                        int w=sum(a[j]-1);                        k1-=w;                        merg(a[j],n,-1);                        j++;                    }                    else{                        k1=p+k1;                        break;                    }                }                merg(a[i],n,1);                r1[i]=j;            }        }        build(1,1,n);        for(i=1;i<=n;i++) g[i].clear();        for(i=0;i<m;i++){            int a,b;            scanf("%d%d",&a,&b);            pp1.id=i;            pp1.to=a;            g[b].push_back(pp1);        }        for(i=1;i<=n;i++){            if(r1[i]-1>=r[i]){                merg1(1,r[i],r1[i]-1,1);            }            int p=(int)g[i].size();            for(j=0;j<p;j++){                c[g[i][j].id]=sum(1,g[i][j].to,i);            }        }        for(i=0;i<m;i++) printf("%I64d\n",c[i]);    }}


0 0
原创粉丝点击