zoukankan      html  css  js  c++  java
  • bzoj3744 Gty的妹子序列

    Description

    给定一个正整数序列a,对于每次询问,输出al...ar中的逆序对数,强制在线。

    Input

    第一行包括一个整数n(1<=n<=50000),表示数列a中的元素数。
    第二行包括n个整数a1...an(ai>0,保证ai在int内)。
    接下来一行包括一个整数m(1<=m<=50000),表示询问的个数。
    接下来m行,每行包括2个整数l、r(1<=l<=r<=n),表示询问al...ar中的逆序
    对数(若ai>aj且i<j,则为一个逆序对)。
    l,r要分别异或上一次询问的答案(lastans),最开始时lastans=0。
    保证涉及的所有数在int内。

    Output

    对每个询问,单独输出一行,表示al...ar中的逆序对数。

    分为sqrt(n)块,预处理每两块间和块内的逆序对数,以及每个位置的数到每块的逆序对数,取前缀和。

    对询问合并区间内块内和块间答案,临时计算两端的答案。

    #include<cstdio>
    #include<cmath>
    #include<algorithm>
    using namespace std;
    int n,m,l,r,la;
    int v[50005];
    int v1[50005],v2[50005],v3[50005];
    int ls[230],rs[230],bp=0;
    int bs[230];
    int bb[230][230];
    int pb[230][50001];
    int sz;
    int cal(int l,int r){
        int m=l+r>>1,ans=0;
        if(l<m)ans+=cal(l,m);
        if(m+1<r)ans+=cal(m+1,r);
        int p1=l,p2=m+1,p3=l;
        while(p1<=m&&p2<=r){
            if(v2[p1]<=v2[p2])v3[p3++]=v2[p1++];
            else ans+=m+1-p1,v3[p3++]=v2[p2++];
        }
        while(p1<=m)v3[p3++]=v2[p1++];
        while(p2<=r)v3[p3++]=v2[p2++];
        for(int i=l;i<=r;i++)v2[i]=v3[i];
        return ans;
    }
    int main(){
        scanf("%d",&n);
        for(int i=1;i<=n;i++){
            scanf("%d",v+i);
            v1[i]=v[i];
        }
        sz=sqrt(n);
        for(int i=1;i<=n;i+=sz){
            ls[bp]=i;
            rs[bp]=i+sz-1;
            if(rs[bp]>n)rs[bp]=n;
            for(int i=ls[bp];i<=rs[bp];i++)v2[i]=v[i];
            bs[bp]=cal(ls[bp],rs[bp]);
            for(int i=ls[bp];i<=rs[bp];i++)v1[i]=v2[i];
            bp++;
        }
        for(int i=0;i<bp;i++){
            for(int j=i+1;j<bp;j++){
                bb[i][j+1]+=bb[i][j];
                for(int a=rs[i],p=rs[j]+1;a>=ls[i];a--){
                    while(p>ls[j]&&v1[p-1]>=v1[a])--p;
                    bb[i][j+1]+=p-ls[j];
                }
            }
        }
        for(int i=0;i<bp;i++){
            for(int j=1;j<=n;j++){
                pb[i+1][j]+=pb[i][j];
                if(j<ls[i])pb[i+1][j]+=lower_bound(v1+ls[i],v1+rs[i]+1,v[j])-v1-ls[i];
                else if(j>rs[i])pb[i+1][j]+=v1+rs[i]+1-upper_bound(v1+ls[i],v1+rs[i]+1,v[j]);
            }
        }
        scanf("%d",&m);
        while(m--){
            int ans=0;
            scanf("%d%d",&l,&r);
            l^=la;r^=la;
            int lb=(l-1)/sz,rb=(r-1)/sz;
            if(lb==rb){
                for(int i=l;i<=r;i++)v2[i]=v[i];
                ans+=cal(l,r);
            }else{
                for(int i=l;i<=rs[lb];i++)v2[i]=v[i];
                if(l<rs[lb])ans+=cal(l,rs[lb]);
                for(int i=ls[rb];i<=r;i++)v2[i]=v[i];
                if(ls[rb]<r)ans+=cal(ls[rb],r);
                for(int i=rs[lb],p=r+1;i>=l;i--){
                    while(p>ls[rb]&&v2[p-1]>=v2[i])--p;
                    ans+=p-ls[rb];
                }
            }
            lb++;
            rb--;
            if(lb<=rb){
                for(int i=l;i<=ls[lb]-1;i++)ans+=pb[rb+1][i]-pb[lb][i];
                for(int i=rs[rb]+1;i<=r;i++)ans+=pb[rb+1][i]-pb[lb][i];
                for(int i=lb;i<=rb;i++)ans+=bs[i];
                if(lb<rb)
                for(int i=lb;i<rb;i++)
                ans+=bb[i][rb+1]-bb[i][i+1];
            }
            printf("%d
    ",la=ans);
        }
        return 0;
    }
  • 相关阅读:
    编译资源收集
    volatile和synchronized到底啥区别?多图文讲解告诉你
    沙雕与大婶 | Mock掉你的外部依赖吧
    全网最详细的一篇Flutter 尺寸限制类容器总结
    一篇带你看懂Flutter叠加组件Stack
    【MySQL】:事务四大特性与隔离级别
    Dubbo 入门-细说分布式与集群
    Java 线程基础知识
    SpringBoot图文教程9—SpringBoot 导入导出 Excel 「Apache Poi」
    搭建博客、自己的小窝?快来看看这些开源静态网站生成器
  • 原文地址:https://www.cnblogs.com/ccz181078/p/5180347.html
Copyright © 2011-2022 走看看