qczrz6v4nhp6u
2025-01-06 16:28:29
操作不弱于区间逆序对,考虑分块,设块长为
对于散块对散块的贡献,直接把所有数加进去查一遍 BIT 即可,复杂度
对于整块对其他的贡献,我们可以考虑预处理出
设
考虑优化 BIT 部分。对于查询,可以压位使得单次计算量减少大约
加了上述几个优化后微调一下块长还是能比较轻松地跑过的。
#include<bits/stdc++.h>
using namespace std;
using ui=unsigned int;
using ll=long long;
using ull=unsigned long long;
using i128=__int128;
using u128=__uint128_t;
using pii=pair<int,int>;
#define fi first
#define se second
// Fast IO
constexpr int N=5e5+5,B=553,S=B+5,T=N/B+5;
struct node{
int l,r;
node(){l=r=0;}
node(int _l,int _r){l=_l,r=_r;}
};
int n,len,q,a[N];pii num[N];
int tot,pos[N];node rngB[T];ll ans[N];
int m;node rngQ[N],rng[N],rng_[N];
ull b[N];int c[N],mdf[N],cnt;
inline void upd(int x){
mdf[++cnt]=x;
static int y,z;y=x&63,z=x>>6;
b[z]|=1ull<<y;
for(++z;z<=len;z+=z&-z)++c[z];
}
inline int ask(int x){
static int y,z;y=x&63,z=x>>6;
static int res;res=__builtin_popcountll(b[z]&((y==63?0:1ull<<(y+1))-1));
for(;z;z-=z&-z)res+=c[z];
return res;
}
inline void clr(int x){
static int z;z=x>>6;
b[z]=0;
for(++z;z<=n;z+=z&-z)
if(c[z])c[z]=0;
else break;
}
void clear(){
for(int i=1;i<=cnt;i++)
clr(mdf[i]);
cnt=0;
}
int op[N],s[N];ll sum[N];
vector<node> vec[T];
int main(){
cin>>n>>q;len=(n>>6)+1;
for(int i=1;i<=n;i++)cin>>a[i],num[i]=make_pair(a[i],n-i+1);
sort(num+1,num+n+1);
for(int i=1;i<=n;i++)a[i]=lower_bound(num+1,num+n+1,make_pair(a[i],n-i+1))-num;
while(rngB[tot].r<n){
++tot;
rngB[tot]=node(rngB[tot-1].r+1,rngB[tot-1].r+B);
}
rngB[tot].r=n;
for(int i=1;i<=tot;i++){
static int l,r;l=rngB[i].l,r=rngB[i].r;
for(int j=l;j<=r;j++)
pos[j]=i;
}
for(int i=1;i<=q;i++){
op[i]=-1;
int mi;cin>>mi;
rngQ[i]=node(m+1,m+mi);
while(mi--){
++m,cin>>rng[m].l>>rng[m].r;
static int _l,_r,_x,_y,_L,_R;
_l=rng[m].l,_r=rng[m].r,_x=pos[_l],_y=pos[_r],_L=rngB[_y].l,_R=rngB[_x].r;
if(_y-_x<=1){
for(int k=_l;k<=_r;k++)ans[i]+=ask(a[k]-1);
for(int k=_l;k<=_r;k++)upd(a[k]);
}
else{
vec[_x+1].emplace_back(i,m);
vec[_y].emplace_back(-i,m);
rng_[m]=node(_R+1,_L);
for(int k=_l;k<=_R;k++)ans[i]+=ask(a[k]-1);
for(int k=_L;k<=_r;k++)ans[i]+=ask(a[k]-1);
for(int k=_l;k<=_R;k++)upd(a[k]);
for(int k=_L;k<=_r;k++)upd(a[k]);
}
}
clear();
}
for(int u=1;u<=tot;u++){
static int _L,_R,_sum;
_L=rngB[u].l,_R=rngB[u].r,_sum=_R-_L+1;
for(int i=_L;i<=_R;i++)++s[a[i]];
for(int i=1;i<=n;i++)s[i]+=s[i-1];
sum[_L]=0;for(int i=_L-1;i>=1;i--)sum[i]=sum[i+1]+_sum-s[a[i]];
sum[_R]=0;for(int i=_R+1;i<=n;i++)sum[i]=sum[i-1]+s[a[i]-1];
for(auto &o:vec[u]){
if(o.l>0)op[o.l]=o.r;
else op[-o.l]=-1;
}
for(int o=1;o<=q;o++){
if(!~op[o])continue;
static int from,p,to;from=rngQ[o].l,p=op[o],to=rngQ[o].r;
for(int i=from;i<p;++i){
ans[o]+=sum[rng[i].l]-sum[rng[i].r+1];
ans[o]-=sum[rng_[i].l]-sum[rng_[i].r];
}
for(int i=p+1;i<=to;++i)
ans[o]+=sum[rng[i].r]-sum[rng[i].l-1];
}
for(int i=1;i<=n;i++)s[i]=0;
}
for(int i=1;i<=q;i++)
cout<<ans[i]<<'\n';
return 0;
}