luogu P5046 [Ynoi2019 模拟赛] Yuno loves sqrt technology I
题面传送门
你会发现这道题时限松得不可思议
这种东西离线都是根号的肯定在线考虑分块。
然后显然预处理\(F_{i,j}\)表示\(i\)到\(j\)块间的答案。同时我们处理\(G_{i,j}\)表示前\(i\)个块中小于等于\(j\)的元素个数用以处理\(F\)
然后两个散块之间直接归并就好了。
散块内部用树状数组预处理。
散块到整块的就考虑枚举每一个散块内的元素然后用\(G\)查询即可。
然后你写完交上去发现\(T\)成40分。
那里面有些不用重复计算减小常数,预处理一下就好了。
代价就是你的代码不能看了。
时间复杂度\(O(n\sqrt n)\)
code:
#include <vector>
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<cmath>
#include<algorithm>
#include<bitset>
#include<set>
#include<map>
#define I inline
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define abs(x) ((x)>0?(x):-(x))
#define l(x) x<<1
#define r(x) x<<1|1
#define re register
#define ll long long
#define db double
#define N 100000
#define K 1000
#define eps (1e-5)
#define mod (1<<31)
#define U unsigned int
using namespace std;
int G[K+5][N+5],n,m,k,z,Fs[N+5],a[N+5],Bh,Id[N+5],head,L[N+5],R[N+5],fl[N+5],fr[N+5],W[N+5],id[N+5],Ws[K+5];ll F[K+5][K+5];
struct ques{int w,id;}B[N+5];I bool cmp(ques x,ques y){return x.w<y.w;}
I void add(int x){while(x<=n) Fs[x]++,x+=x&-x;}
I int find(int x){int ans=0;while(x) ans+=Fs[x],x-=x&-x;return ans;}
I void clear(int x){while(x<=n&&Fs[x]) Fs[x]=0,x+=x&-x;}
static char buf[10000000],*p1=buf,*p2=buf;
#define getchar() p1==p2&&(p2=(p1=buf)+fread(buf,1,1000000,stdin),p1==p2)?EOF:*p1++
I void read(int &x){
char s=getchar();x=0;while(s<'0'||s>'9') s=getchar();
while(s>='0'&&s<='9') x=x*10+s-48,s=getchar();
}
char OS[N+5];int Oh;
I void print(ll x){while(OS[++Oh]=x%10+48,x/=10);while(Oh) putchar(OS[Oh--]);putchar('\n');}
signed main(){
freopen("1.in","r",stdin);freopen("1.out","w",stdout);
re int i,j,h,xn,yn,x,y;re ll Lastans=0;read(n);read(m);k=sqrt(n/6);for(i=1;i<=n;i++) read(a[i]),B[i]=(ques){a[i],i};
for(i=0;i<=n/k;i++) fl[i]=max(1,i*k),fr[i]=min(n,i*k+k-1);
for(i=0;i<=n/k;i++){
for(j=fl[i];j<=fr[i];j++) G[i][a[j]]++;memcpy(G[i+1],G[i],sizeof(G[i]));
for(j=1;j<=n;++j) G[i][j]+=G[i][j-1];head=0;sort(B+fl[i],B+fr[i]+1,cmp);for(j=fl[i];j<=fr[i];j++) Id[B[j].id]=j;
for(j=fl[i];j<=fr[i];j++) add(a[j]),j!=fl[i]&&(L[j]=L[j-1]+find(n)-find(a[j]));for(j=fl[i];j<=fr[i];j++) clear(a[j]);
for(j=fr[i];j>=fl[i];j--) add(a[j]),R[j]=R[j+1]+find(a[j]-1);for(j=fl[i];j<=fr[i];j++) clear(a[j]);
}
for(i=1;i<=n;i++) W[i]=B[i].w,id[i]=B[i].id;
for(i=0;i<=n/k;i++){
for(j=fl[i];j<=fr[i];j++) Ws[i]+=G[i-1][a[j]];
}
for(i=0;i<=n/k;++i){
for(j=i;j<=n/k;++j){
i&&(Lastans=F[i][j-1]);Lastans+=L[fr[j]];Lastans+=((j?G[j-1][n]:0)-(i?G[i-1][n]:0))*(fr[j]-fl[j]+1);if(i==j){F[i][j]=Lastans;continue;}
Lastans-=Ws[j];if(i){for(h=fl[j];h<=fr[j];++h) Lastans+=G[i-1][a[h]];}F[i][j]=Lastans;
}
}Lastans=0;//return 0;
while(m--){
read(x);read(y);/*x^=Lastans;y^=Lastans;*/xn=x/k;yn=y/k;
if(xn==yn){
Lastans=L[y]-(x==fl[xn]?0:L[x-1]);for(i=x;i<=y;i++) Fs[Id[i]]++;
for(i=fl[xn];i<=fr[xn];++i) Fs[i]+=Fs[i-1],B[i].id<x&&(Lastans-=Fs[i]),Fs[i-1]=0;Fs[fr[xn]]=0;
print(Lastans);continue;
}
Lastans=F[xn+1][yn-1]+R[x]+L[y]+(y-fl[yn]+1)*(G[yn-1][n]-G[xn][n]);
yn--;for(i=x;i<=fr[xn];++i) Lastans+=G[yn][a[i]]-G[xn][a[i]];for(i=fl[yn+1];i<=y;++i) Lastans-=G[yn][a[i]]-G[xn][a[i]];yn++;
z=fr[xn]-x+1;j=fl[xn];h=fl[yn];while(z&&j<=fr[xn]&&h<=fr[yn]){
while(h<=fr[yn]&&(j==fr[xn]+1||W[j]>W[h])) id[h++]<=y&&(Lastans+=z);
z-=(id[j++]>=x);
}
print(Lastans);
}
}