题解:P8419 [THUPC 2022 决赛] riapq
不弱于区间逆序对,考虑以
记
那么修改就是对于
对于
对于
考虑
散块对散块的贡献,直接暴力树状数组即可。被卡常的话可能要换成归并排序。
总的时间复杂度为
#include<bits/stdc++.h>
#define ll long long
#define rd read()
#define gc pa == pb && (pb = (pa = buf) + fread(buf, 1, 100000, stdin), pa == pb) ? EOF : *pa++
using namespace std;
static char buf[100000], * pa(buf), * pb(buf);
inline int read()
{
unsigned int x=0,s=gc;
while(!isdigit(s))s=gc;
while(isdigit(s))x=(x<<1)+(x<<3)+(s^48),s=gc;
return x;
}
const int N=200003,block=1000,S=N/block+3;
int n,m,tot,c,sa,sb;ll b[N];
int p[N],A[N],B[N],a[N],f[N],bl[N],L[S],R[S],w[S][N];
inline int get(int x,int y){return __builtin_popcountll(x&(((y&63)==63?0:(1ull<<((y&63)+1)))-1));}
struct BIT
{
int c[N];
inline void add(int x){for(;x<=n;x+=x&-x)++c[x];}
inline void del(int x){for(;x<=n;x+=x&-x)--c[x];}
inline int ask(int x){int s=0;for(;x;x^=x&-x)s+=c[x];return s;}
}s[S],g[S],G;
inline bool cmp(int x,int y){return a[x]<a[y];}
inline void merge(){for(int i=1,j=1;i<=sb;b[B[i]]+=j-1,++i)while(j<=sa&&a[A[j]]<=a[B[i]])++j;}
inline void add(int l,int r)
{
c=l-1,G.add(l),G.del(r+1);if(!c)return;sa=sb=0;
for(int i=1;i<bl[c];++i)g[i].add(l),g[i].del(r+1);
if(bl[l]==bl[r]){for(int i=L[bl[l]];i<=R[bl[l]];++i)if(p[i]>=l&&p[i]<=r)B[++sb]=p[i];}
else
{
if(bl[l]+1<bl[r])for(int i=L[bl[c]];i<=c;++i)s[bl[l]+1].add(a[i]),s[bl[r]].del(a[i]);
int p1=L[bl[l]],p2=L[bl[r]];
while(p1<=R[bl[l]]||p2<=R[bl[r]])
if(p[p1]<l)++p1;
else if(p[p2]>r)++p2;
else if(p1>R[bl[l]])B[++sb]=p[p2++];
else if(p2>R[bl[r]]||a[p[p1]]<a[p[p2]])B[++sb]=p[p1++];
else B[++sb]=p[p2++];
}
for(int i=L[bl[c]];i<=R[bl[c]];++i)if(p[i]<=c)A[++sa]=p[i];
merge();
}
inline ll ask(int x)
{
ll res=1ll*f[x]*G.ask(x)-b[x],v=a[x];
for(int i=1;i<bl[x];++i)res-=1ll*g[i].ask(x)*w[i][v]+s[i].ask(v);
res-=s[bl[x]].ask(v);
return res;
}
signed main()
{
n=rd,m=rd,tot=(n-1)/block+1;
for(int i=1;i<=tot;++i)L[i]=R[i-1]+1,R[i]=i*block;R[tot]=n;
for(int i=1;i<=n;bl[i]=(i-1)/block+1,p[i]=i,++i)a[i]=rd;
for(int i=1;i<=n;++i)G.add(a[i]),f[i]=G.ask(a[i]);
for(int i=1;i<=tot;++i)sort(p+L[i],p+R[i]+1,cmp);
memset(G.c,0,sizeof(G.c));
for(int i=1;i<=n;++i)++w[bl[i]][a[i]];
for(int j=1;j<=tot;++j)for(int i=2;i<=n;++i)w[j][i]+=w[j][i-1];
for(int i=1,op,l;i<=m;++i)
{
op=rd,l=rd;
if(op==1)add(l,rd);
if(op==2)cout<<ask(l)<<'\n';
}
return 0;
}
还是分块,考虑直接维护
对于
对于
对于
考虑对于
每个元素的值域分块就需要做到
时空复杂度均为
#include<bits/stdc++.h>
#define ll long long
#define rd read()
#define gc pa == pb && (pb = (pa = buf) + fread(buf, 1, 100000, stdin), pa == pb) ? EOF : *pa++
using namespace std;
static char buf[100000], * pa(buf), * pb(buf);
inline int read()
{
unsigned int x=0,s=gc;
while(!isdigit(s))s=gc;
while(isdigit(s))x=(x<<1)+(x<<3)+(s^48),s=gc;
return x;
}
const int N=200003,B1=20,B2=B1*B1,B3=B2*B1;
const int S1=N/B1+1,S2=N/B2+1,S3=N/B3+1;
int n,m,tot1,tot2,tot3,cnt;
int op[N],f[N],al[N],ar[N],b1[N],b2[N],b3[N],a[N],tg[S2][S2];
int L1[S1],R1[S1],L2[S2],R2[S2],L3[S3],R3[S3],sum[B2*N<<1];
struct node{int x,y,z;};vector<node> q[N];
ll b[N];short w[S2][N];
struct blk
{
int c[N],t[S2];
inline void add(int x)
{
for(int i=x;i<=R2[b2[x]];++i)++c[i];
for(int i=b2[x]+1;i<=tot2;++i)++t[i];
}
inline int ask(int x){return c[x]+t[b2[x]];}
}G;
struct blk2
{
int t[N],t1[S1],t2[S2],t3[S3];
inline void add(int x,int v){t[x]+=v,t1[b1[x]]+=v,t2[b2[x]]+=v,t3[b3[x]]+=v;}
inline int ask(int x)
{
int s=0;
for(int i=1;i<b3[x];++i)s+=t3[i];
for(int i=b2[L3[b3[x]]];i<b2[x];++i)s+=t2[i];
for(int i=b1[L2[b2[x]]];i<b1[x];++i)s+=t1[i];
for(int i=L1[b1[x]];i<=x;++i)s+=t[i];
return s;
}
}tk[S3],ck[S2];
inline void ADD(int x,int y,int v){tk[b1[x]].add(y,v),ck[x].add(y,v);}
inline ll ASK(int x,int y)
{
ll res=0;
for(int i=1;i<b1[x];++i)res+=tk[i].ask(y);
for(int i=L1[b1[x]];i<=x;++i)res+=ck[i].ask(y);
return res;
}
inline void add(int l,int r)
{
if(b2[l]==b2[r]){for(int i=l;i<=r;++i)b[i]+=f[i]-sum[++cnt];return;}
add(l,R2[b2[l]]),add(L2[b2[r]],r);
for(int i=b2[l]+1;i<b2[r];++i)++tg[b2[l]+1][i];
for(int i=l;i<=R2[b2[l]];++i)ADD(b2[l]+1,a[i],1),ADD(b2[r],a[i],-1);
}
inline void irt(int l,int r)
{
if(!l)return;
if(b2[l]==b2[r]){q[l-1].push_back({l,r,cnt}),cnt+=r-l+1;return;}
q[l-1].push_back({l,R2[b2[l]],cnt}),cnt+=R2[b2[l]]-l+1;
q[l-1].push_back({L2[b2[r]],r,cnt}),cnt+=r-L2[b2[r]]+1;
}
inline void irt2(int x){q[L2[b2[x]]-1].push_back({x,x,cnt});++cnt;}
inline ll ask(int x)
{
ll res=b[x];int v=a[x],c=0;
for(int i=1;i<b2[x];++i)res+=1ll*w[i][v]*(c+=tg[i][b2[x]]);
res+=1ll*(c+tg[b2[x]][b2[x]])*(f[x]-sum[++cnt]);
return res+ASK(b2[x],v);
}
signed main()
{
n=rd,m=rd,tot1=(n-1)/B1+1,tot2=(n-1)/B2+1,tot3=(n-1)/B3+1,cnt=1;
for(int i=1;i<=tot1;++i)L1[i]=R1[i-1]+1,R1[i]=i*B1;R1[tot1]=n;
for(int i=1;i<=tot2;++i)L2[i]=R2[i-1]+1,R2[i]=i*B2;R2[tot2]=n;
for(int i=1;i<=tot3;++i)L3[i]=R3[i-1]+1,R3[i]=i*B3;R3[tot3]=n;
for(int i=1;i<=n;++i)a[i]=rd,b1[i]=(i-1)/B1+1,b2[i]=(i-1)/B2+1,b3[i]=(i-1)/B3+1;
for(int i=1;i<=n;++i)++w[b2[i]][a[i]];
for(int j=1;j<=tot2;++j)for(int i=2;i<=n;++i)w[j][i]+=w[j][i-1];
for(int i=1;i<=m;++i){op[i]=rd,al[i]=rd;if(op[i]==1)irt(al[i],ar[i]=rd);if(op[i]==2)irt2(al[i]);}
for(int i=1;i<=n;f[i]=G.ask(a[i]),++i)
{
G.add(a[i]);
for(auto [l,r,id]:q[i])for(int j=l;j<=r;++j)sum[id+j-l]=G.ask(a[j]);
}
cnt=0;
for(int i=1;i<=m;++i)
if(op[i]==1)add(al[i],ar[i]);
else cout<<ask(al[i])<<'\n';
return 0;
}