【Ynoi2019】Yuno loves sqrt technology I
【Ynoi2019】Yuno loves sqrt technology I
by AmanoKumiko
Description
给出长为的排列,有次询问
每次询问一个区间的逆序对数
强制在线
Input
第一行两个数
然后一行个数读入排列
Output
一共行,每行一个数表示答案
Sample Input
4 1
1 4 2 3
2 4
Sample Output
2
Data Constraint
Solution
非常精妙地运用了归并思想
对序列分块,先把贡献拆开
1.块与块
设表示第到第块的贡献
可以写成(这个也太妙了吧
即第和第块产生的贡献
2.点与块
设表示前块中的数的个数,可以预处理
设分别表示一段前缀和后缀的贡献,扫一遍就行了
3.点与点
直接归并
PS:这题也太卡了吧。。。
Code
#include<bits/stdc++.h>
using namespace std;
#define Fo(i,a,b) for(int i=a;i<=b;i++)
#define Fd(i,a,b) for(int i=a;i>=b;i--)
#define LL long long
#define N 100010
#define M 650
inline char gc()
{
static char buf[1048576],*p1,*p2;
return p1==p2&&(p2=(p1=buf)+fread(buf,1,1048576,stdin),p1==p2)?EOF:*p1++;
}
inline int read()
{
char ch=gc();int r=0,w=1;
for(;ch<'0'||ch>'9';ch=gc())if(ch=='-')w=-1;
for(;'0'<=ch&&ch<='9';ch=gc())r=r*10+(ch-'0');
return r*w;
}
namespace IO{
const int sz=1<<22;
char b[sz+5],*t=b,p[105];
inline void flush(){fwrite(b,1,t-b,stdout),t=b;}
inline void pc(char x){*t++=x;if(t-b==sz)flush();}
template<class T>void write(T x,char c='\n'){
if(x==0)pc('0');int t=0;
for(;x;x/=10)p[++t]=x%10+'0';
for(;t;--t)pc(p[t]);pc(c);
}
struct F{~F(){flush();}}f;
}
using IO::write;
int ql[N],qr[N],tl,tr;
int n,m,a[N],b[M][M],pre[N],suf[N],cnt[M][N],tmp[N],B,sz,L[M],R[M],be[N],len[M],pos[N];
LL ans,f[M][M];
struct tree{
int sum[N];
int lowbit(int x){return -x&x;}
void modify(int x,int y){while(x<=n)sum[x]+=y,x+=lowbit(x);}
int qur(int x){int res=0;while(x)res+=sum[x],x-=lowbit(x);return res;}
}t;
int main(){
n=read();m=read();
Fo(i,1,n)pos[a[i]=read()]=i;
B=160;
sz=n/B+1;
Fo(i,1,sz){
L[i]=R[i-1]+1;R[i]=min(n,L[i]+B-1);
len[i]=R[i]-L[i]+1;
if(len[i]<=0)continue;
Fo(j,L[i],R[i])b[i][j-L[i]+1]=a[j],be[j]=i,tmp[a[j]]++;
sort(b[i]+1,b[i]+len[i]+1);
Fo(j,L[i],R[i]){
pre[j]=(j-1>=L[i]?pre[j-1]:0);
pre[j]+=j-L[i]-t.qur(a[j]);
t.modify(a[j],1);
}
int nw=pre[R[i]];
Fo(j,L[i],R[i]){
t.modify(a[j],-1);
suf[j]=nw;nw-=t.qur(a[j]);
}
Fd(j,n,1)tmp[j]+=tmp[j+1];
Fo(j,1,n)cnt[i][j]=cnt[i-1][j]+tmp[j],tmp[j]=0;
}
Fd(i,sz,1){
f[i][i]=pre[R[i]];
Fo(j,i+1,sz){
f[i][j]=f[i+1][j]+f[i][j-1]-f[i+1][j-1];
int t=1;
Fo(k,1,len[j]){while(b[i][t]<=b[j][k]&&t<=len[i])t++;f[i][j]+=len[i]-t+1;}
}
}
Fo(i,1,m){
int l=read(),r=read();
l^=ans;r^=ans;
if(be[l]==be[r]){
if(l==L[be[l]]){ans=pre[r];write(ans);continue;}
ans=pre[r]-pre[l-1];
tl=tr=0;
Fo(j,1,len[be[l]]){
if(pos[b[be[l]][j]]<=l-1)ql[++tl]=b[be[l]][j];
else if(pos[b[be[l]][j]]<=r)qr[++tr]=b[be[l]][j];
}
int t=1;
Fo(j,1,tr){while(ql[t]<=qr[j]&&t<=tl)t++;ans-=tl-t+1;}
write(ans);
}else{
ans=f[be[l]+1][be[r]-1]+suf[l]+pre[r]+1ll*(R[be[l]]-l+1)*(R[be[r]-1]-L[be[l]+1]+1);
Fo(j,l,R[be[l]])ans-=cnt[be[r]-1][a[j]]-cnt[be[l]][a[j]];
Fo(j,L[be[r]],r)ans+=cnt[be[r]-1][a[j]+1]-cnt[be[l]][a[j]+1];
int wz=1,nw=0,nw1=0;
Fo(j,1,len[be[l]])if(pos[b[be[l]][j]]>=l)
{
while(wz<=len[be[r]]&&b[be[r]][wz]<b[be[l]][j])nw+=(pos[b[be[r]][wz]]<=r),wz++;
if(nw==r-L[be[r]]+1)
{
ans+=nw*(R[be[l]]-l+1-nw1);
break;
}
ans+=nw;nw1++;
}
write(ans);
}
}
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话