[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
原文地址:https://www.cnblogs.com/PYWBKTDA/p/13826187.html