题解 P5012 【水の数列】
这题的题目背景使我们明白,原来神题都是多次加强造出来的(划掉
观察题目中给出的这个得分的性质,发现随着
对于限定区间个数 分块什么时候是数据结构了
对于一个确定的
小于等于
Show the Code
#include<cstdio>
#include<vector>
#include<cmath>
#include<algorithm>
#define get_block(x) (x-1)/block+1
#define min(a,b) ((a)<(b)? (a):(b))
typedef long long ll;
std::vector<int> t[1000001];
ll v[1000001];
int fa[1000001],size[1000001],a[1000001],c[1000001],mx[1000001],maxn[1001];
inline int read() {
register int x=0,f=1;register char s=getchar();
while(s>'9'||s<'0') {if(s=='-') f=-1;s=getchar();}
while(s>='0'&&s<='9') {x=x*10+s-'0';s=getchar();}
return x*f;
}
inline void swap(int &x,int &y) {int tmp=y;y=x;x=tmp;}
inline int find(int x) {return x==fa[x]? x:fa[x]=find(fa[x]);}
inline void merge(int x,int y,ll &res1,int &res2) {
int fx=find(x),fy=find(y);
if(fx!=fy) {
res1-=(ll)size[fx]*size[fx]+(ll)size[fy]*size[fy]; --res2;
fa[fy]=fx;size[fx]+=size[fy];res1+=(ll)size[fx]*size[fx];
}
}
inline bool cmp(int x,int y) {return v[x]*1ll*c[y]<v[y]*1ll*c[x];}
int main() {
int n=read(),T=read(),num=0,block=sqrt(n);
for(register int i=1;i<=n;++i) c[++num]=a[i]=read(),fa[i]=i;
std::sort(c+1,c+1+num); num=std::unique(c+1,c+1+num)-c-1;
for(register int i=1;i<=n;++i) {a[i]=std::lower_bound(c+1,c+1+num,a[i])-c;t[a[i]].push_back(i);}
ll now=0; int tot=0;
v[0]=-1,c[0]=1;
for(register int x=1;x<=num;++x) {
for(register int i=0;i<t[x].size();++i) {size[t[x][i]]=1; ++now; ++tot;}
for(register int i=0;i<t[x].size();++i) {
if(t[x][i]!=1&&a[t[x][i]-1]<=x) merge(t[x][i],t[x][i]-1,now,tot);
if(t[x][i]!=n&&a[t[x][i]+1]<=x) merge(t[x][i],t[x][i]+1,now,tot);
}
v[x]=now;
if(cmp(mx[tot],x)) {
mx[tot]=x;
if(cmp(maxn[get_block(tot)],x)) maxn[get_block(tot)]=x;
}
}
ll ans=0;
while(T--) {
int a=read()%n,b=read()%n,x=read()%n,y=read()%n;
int l=((a*1ll*ans%n+x-1)%n+n)%n+1,r=((b*1ll*ans%n+y-1)%n+n)%n+1;
if(l>r) swap(l,r);
int bl=get_block(l),br=get_block(r),id=0;
if(bl==br) {for(register int i=l;i<=r;++i) if(cmp(id,mx[i])) id=mx[i];}
else {
for(register int i=l;i<=min(bl*block,n);++i) if(cmp(id,mx[i])) id=mx[i];
for(register int i=bl+1;i<br;++i) if(cmp(id,maxn[i])) id=maxn[i];
for(register int i=(br-1)*block+1;i<=r;++i) if(cmp(id,mx[i])) id=mx[i];
}
if(id==0) {printf("-1 -1\n%d %d %d\n",l,r,ans);ans=1%n;}
else {printf("%lld %d\n%d %d %d\n",v[id],c[id],l,r,ans);ans=(v[id]%n)*1ll*(c[id]%n)%n;}
}
return 0;
}