zoukankan      html  css  js  c++  java
  • [loj3341]时代的眼泪

    题意即求在区间$[l,r]$中且权值在$[x,y]$中的逆序对个数

    考虑分块,逆序对个数包含4部分:

    1.左/右块外内部,预处理出$i$到其所在块的块首/尾,小于/小于等于$j$(需要对$j$离散)的数即可;

    2.左块外与右块外,预处理出每个块内数的顺序,来对左/右块外排序,再归并排序即可;

    3.左/右块外到块内,预处理出前$i$个块中小于/小于等于$j$的数个数;

    4.块内部,对权值区间$[x,y]$容斥,变为$[1,y]-[1,x)-[1,x)与[x,y]$

    $[1,y]$和$[1,x)$类似,预处理第$i$个块中的$j$(离散)在 第$k$个块中比其小的数的个数,特别的,当$k=i$定义为$i$到其所在块块首小于$j$的数个数(即1.),然后对$j$和$k$两维求前缀和即可(预处理过程中,为了避免二分,可以先枚举$k$再枚举$j$)

    $[1,x)$与$[x,y]$,答案分为两类:1.块与块之间;2.块内部

    第1个比较好做,枚举前$i$个块,即求出前$i-1$个块中$[1,x)$的点个数*第$i$个块中$[x,y]$的点个数,用3.的预处理即可

    第2个对第$i$个块预处理出$j$是否在$k$之前(离散),那么即求$sum_{j=1}^{x-1}sum_{k=x}^{y}f[j][k]$,二位前缀和来计算即可

    特别的,当$l$和$r$在同一个连通块中,直接用第1种做法,再对询问区间容斥一下即可

    时间复杂度为$o(nsqrt{n})$,常数极大,可能无法通过

      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 #define N 100005
      4 #define K 300
      5 #define NdK 400
      6 vector<int>v,vl,vr;
      7 int n,m,l,r,x,y,a[N],b[N],bl[N],st[N],ed[N],id[N];
      8 int g1[N][K+10],g2[N][K+10],g3[NdK][N],g4[NdK][N],f1[NdK][K+10][NdK],f2[NdK][K+10][K+10];
      9 long long ans;
     10 int calc1(int k){//统计[st[bl[k]],k]范围内的答案 
     11     int z=g3[bl[k]][x]-g3[bl[k]-1][x],ans=0;
     12     for(int i=st[bl[k]];i<=k;i++)//xx<=id[x]<id[i]
     13         if ((x<=a[i])&&(a[i]<=y))ans+=g1[i][id[i]]-g1[i][z];
     14     return ans;
     15 }
     16 int calc2(int k){//统计[k,ed[bl[k]]范围内的答案 
     17     int z=g4[bl[k]][y]-g4[bl[k]-1][y]-1,ans=0;
     18     for(int i=k;i<=ed[bl[k]];i++)//id[i]<id[x]<=y
     19         if ((x<=a[i])&&(a[i]<=y))ans+=g2[i][z]-g2[i][id[i]];
     20     return ans;
     21 }
     22 int calc3(int l,int r){//统计[l,r]范围内的答案 
     23     int z=g3[bl[l]][x]-g3[bl[l]-1][x],ans=0;
     24     for(int i=l;i<=r;i++)//id[i]<id[x]<=yy,l<=x<=i
     25         if ((x<=a[i])&&(a[i]<=y))ans+=g1[i][id[i]]-g1[i][z]-g1[l-1][id[i]]+g1[l-1][z];
     26     return ans;
     27 }
     28 long long calc4(int l,int r,int x){//统计[bl[l],ed[r]],[1,x]的答案 
     29     int ans=0;
     30     for(int i=l;i<=r;i++){
     31         int y=g4[i][x]-g4[i-1][x]-1;
     32         if (y>=0)ans+=f1[i][y][i]-f1[i][y][l-1];
     33     }
     34     return ans;
     35 }
     36 int merge(int x1,int y1,int x2,int y2){//归并排序[x1,y1]和[x2,y2]并统计答案 
     37     vl.clear();
     38     vr.clear();
     39     for(int i=x1;i<=y1;i++)
     40         if ((x<=a[i])&&(a[i]<=y))b[id[i]]=a[i];
     41     for(int i=0;i<=ed[bl[x1]]-st[bl[x1]];i++)
     42         if (b[i]){
     43             vl.push_back(b[i]);
     44             b[i]=0;
     45         }
     46     for(int i=x2;i<=y2;i++)
     47         if ((x<=a[i])&&(a[i]<=y))b[id[i]]=a[i];
     48     for(int i=0;i<=ed[bl[x2]]-st[bl[x2]];i++)
     49         if (b[i]){
     50             vr.push_back(b[i]);
     51             b[i]=0;
     52         }
     53     int ans=0;
     54     for(int i=0,j=0,k=0;(i<vl.size())||(j<vr.size());k++)
     55         if ((i<vl.size())&&((j==vr.size())||(vl[i]<vr[j])))i++;
     56         else{
     57             j++;
     58             ans+=k--;
     59         }
     60     return ans;
     61 }
     62 int main(){
     63     freopen("tears.in","r",stdin);
     64     freopen("tears.out","w",stdout);
     65     scanf("%d%d",&n,&m);
     66     for(int i=1;i<=n;i++)scanf("%d",&a[i]);
     67     for(int i=1;i<=n;i++){
     68         bl[i]=i/K+1;
     69         if (K==1)bl[i]--;
     70         if (!st[bl[i]])st[bl[i]]=i;
     71         ed[bl[i]]=i;
     72     }
     73     for(int i=1;i<=bl[n];i++){
     74         v.clear();
     75         for(int j=st[i];j<=ed[i];j++)v.push_back(a[j]);
     76         sort(v.begin(),v.end());
     77         for(int j=st[i];j<=ed[i];j++)id[j]=lower_bound(v.begin(),v.end(),a[j])-v.begin();
     78         for(int j=0;j<=ed[i]-bl[i];j++){
     79             g1[st[i]][j]=(a[st[i]]<v[j]);
     80             for(int k=st[i]+1;k<=ed[i];k++)g1[k][j]=g1[k-1][j]+(a[k]<v[j]);
     81             g2[ed[i]][j]=(a[ed[i]]<=v[j]);
     82             for(int k=ed[i]-1;k>=st[i];k--)g2[k][j]=g2[k+1][j]+(a[k]<=v[j]);
     83         }
     84         for(int j=1,k=0;j<=n;j++){
     85             while ((k<v.size())&&(v[k]<j))k++;
     86             g3[i][j]=g3[i-1][j]+k;
     87             g4[i][j]=g4[i-1][j]+k;
     88             if ((k<v.size())&&(v[k]==j))g4[i][j]++;
     89         }
     90         for(int j=1;j<i;j++){
     91             f1[i][0][j]=g3[j][v[0]]-g3[j-1][v[0]];
     92             for(int k=1;k<v.size();k++)f1[i][k][j]=f1[i][k-1][j]+g3[j][v[k]];
     93             for(int k=0;k<v.size();k++)f1[i][k][j]+=f1[i][k][j-1];
     94         }
     95         for(int j=st[i];j<=ed[i];j++)f1[i][id[j]][i]=g1[j][id[j]];
     96         for(int j=1;j<=ed[i]-st[i];j++)f1[i][j][i]+=f1[i][j-1][i];
     97         for(int j=0;j<=ed[i]-st[i];j++)f1[i][j][i]+=f1[i][j][i-1];
     98         for(int j=st[i];j<=ed[i];j++)
     99             for(int k=j+1;k<=ed[i];k++)
    100                 if (a[j]<a[k])f2[i][id[j]][id[k]]=1;
    101         for(int j=1;j<=ed[i]-st[i];j++){
    102             f2[i][j][0]+=f2[i][j-1][0];
    103             f2[i][0][j]+=f2[i][0][j-1];
    104         }
    105         for(int j=1;j<=ed[i]-st[i];j++)
    106             for(int k=1;k<=ed[i]-st[i];k++)f2[i][j][k]+=f2[i][j-1][k]+f2[i][j][k-1]-f2[i][j-1][k-1];
    107     }
    108     for(int i=1;i<=m;i++){
    109         scanf("%d%d%d%d",&l,&r,&x,&y);
    110         if (bl[l]==bl[r]){
    111             printf("%d
    ",calc3(l,r));
    112             continue;
    113         }
    114         ans=calc1(r)+calc2(l)+merge(l,ed[bl[l]],st[bl[r]],r);
    115         for(int j=st[bl[r]];j<=r;j++)//x<=a[x]<a[j]
    116             if ((x<=a[j])&&(a[j]<=y))ans+=g3[bl[r]-1][a[j]]-g3[bl[r]-1][x]-g3[bl[l]][a[j]]+g3[bl[l]][x];
    117         for(int j=l;j<=ed[bl[l]];j++)//a[j]<a[x]<=y
    118             if ((x<=a[j])&&(a[j]<=y))ans+=g4[bl[r]-1][y]-g4[bl[r]-1][a[j]]-g4[bl[l]][y]+g4[bl[l]][a[j]];
    119         l=bl[l]+1;
    120         r=bl[r]-1;
    121         if (l<=r){
    122             ans+=calc4(l,r,y)-calc4(l,r,x-1);
    123             for(int j=l;j<=r;j++)ans-=(g3[j-1][x]-g3[l-1][x])*(g4[j][y]-g3[j][x]-g4[j-1][y]+g3[j-1][x]);
    124             for(int j=l;j<=r;j++){
    125                 int xx=g3[j][x]-g3[j-1][x],yy=g4[j][y]-g4[j-1][y]-1;
    126                 ans-=f2[j][xx-1][yy]-f2[j][xx-1][xx-1];
    127             }
    128         }
    129         printf("%lld
    ",ans);
    130     }
    131 }
    View Code
  • 相关阅读:
    Hibernate框架 主配置文件 Hibernate.cfg.xml 映射配置 说明
    Hibernate框架 初识 ORM概念 搭建Hibernate环境 Hibernate Api
    Struts 框架 之 文件上传下载案例
    Struts 之 通配符 路径匹配 常量用法 配置默认值
    Struts框架之 执行流程 struts.xml 配置详细
    Struts 框架 之 Hello World
    JSP include HTML出现乱码 问题解决
    java 集合 Connection 栈 队列 及一些常用
    java Gui编程 事件监听机制
    java 网络编程 UDP TCP
  • 原文地址:https://www.cnblogs.com/PYWBKTDA/p/13826187.html
Copyright © 2011-2022 走看看