luoguP5609 [Ynoi2013] 对数据结构的爱 题解

考虑统计要减去多少个\(p\),不难发现一段区间最多减去\(len\)\(p\),直接维护线段树,维护出每一个区间的断点(相当于分段函数),在合并两个子区间断点的时候,如果左区间\(i\)最大能和右区间\(j\)合并,那么左区间\(i+1\)最小也不能和\(j-1\)合并,因为\(i+1\)的需求值一定比\(i\)大,那么至少要减去\(i+j+1\)\(p\)才可能贡献答案。(注:第\(i\)个和第\(i+1\)个差至少为\(p\),如果不为\(p\),考虑一定可以减少第\(i\)个使得答案恰好卡在第\(i+1\)个比第\(i\)个多的减\(p\)的那一个数上,也可以认为把第\(i\)个数扔进拍出来的答案一定不比第\(i+1\)个扔进去小,但第\(i+1\)个比第\(i\)个多减去了\(p\)。)

#include <bits/stdc++.h>
#define int long long
#define lid (id<<1)
#define rid (id<<1|1)
using namespace std;
const int inf=1e18;
const int maxn=1e6+10;
int n,m,modd,a[maxn],x,y,z,ans,ll1;
struct edge{
	int sum;
	vector<int>shu;
}tree[maxn<<2];
inline void push_up(int id){
	tree[id].sum=tree[lid].sum+tree[rid].sum;
	ll1=0;
	for(int i=0;i<=tree[lid].shu.size()-2;i++){
		if(ll1){
			ll1--;
		}
		while(ll1<=tree[rid].shu.size()-2){
			if(tree[lid].shu[i+1]-1-i*modd+tree[lid].sum<tree[rid].shu[ll1]){
				break;
			}
			tree[id].shu[i+ll1]=min(tree[id].shu[i+ll1],max(tree[lid].shu[i],tree[rid].shu[ll1]+i*modd-tree[lid].sum));
			ll1++;
		}
	}
	return;
}
inline void build(int id,int l,int r){
	for(int i=1;i<=r-l+3;i++){
		tree[id].shu.push_back(inf);
	}
	tree[id].shu[0]=-inf;
	if(l==r){
		tree[id].sum=a[l];
		tree[id].shu[1]=modd-a[l];
		return;
	}
	int mid=(l+r)>>1;
	build(lid,l,mid);
	build(rid,mid+1,r);
	push_up(id);
	return;
}
inline int query(int id,int l,int r,int q,int w,int qw){
	if(q<=l&&r<=w){
		int pos=upper_bound(tree[id].shu.begin(),tree[id].shu.end(),qw)-tree[id].shu.begin()-1;
		return qw+tree[id].sum-pos*modd;
	}
	int mid=(l+r)>>1;
	if(w<=mid){
		return query(lid,l,mid,q,w,qw);
	}
	else if(q>mid){
		return query(rid,mid+1,r,q,w,qw);
	}
	else{
		return query(rid,mid+1,r,q,w,query(lid,l,mid,q,w,qw));
	}
}
signed main(){
	ios::sync_with_stdio(0);
	cin.tie(0),cout.tie(0);
	cin>>n>>m>>modd;
	for(int i=1;i<=n;i++){
		cin>>a[i];
	}
	build(1,1,n);
	while(m--){
		cin>>x>>y>>z;
		x^=ans,y^=ans,z^=ans;
		ans=query(1,1,n,x,y,z);
		cout<<ans<<'\n';
		ans=(ans%n+n)%n;
	}
	return 0;
}

卡常后代码:

#include <bits/stdc++.h>
#define lid (id<<1)
#define rid (id<<1|1)
#define ll long long
using namespace std;
const ll inf=1e18;
const int maxn=1.5e6+10;
int n,m,a[maxn],x,y,z,nn,tp,st[maxn];
ll modd,ans;
namespace FastIO{
	const int SIZE=(1<<21)+1;
	char ibuf[SIZE],obuf[SIZE],*iS,*iT,*oS=obuf,*oT=obuf;
	char* flush(){fwrite(obuf,1,oT-oS,stdout);return oT=obuf;}
	struct Flusher{~Flusher(){flush();}}flusher;
	inline char gc(){return iS==iT && (iT=(iS=ibuf)+fread(ibuf,1,SIZE,stdin),iS==iT)?EOF:*iS++;}
	inline void pc(char c){if(oT==oS+SIZE) flush();*oT++=c;}
	template<typename T=int>
	T read(){T x=0;bool fl=0;char ch=gc();for(;ch<'0' || ch>'9';ch=gc())if(ch=='-')fl=1;for(;ch>='0' && ch<='9';ch=gc()) x=x*10+(ch-'0');return fl?-x:x;}
	template<typename T>
	void write(T x){if(x>=10) write(x/10);pc(x%10+'0');}
}
using FastIO::gc;
using FastIO::pc;
using FastIO::read;
using FastIO::write;
struct edge{
	ll sum;
	int len;
	vector<ll>shu;
}tree[maxn<<2];
__attribute__((always_inline)) inline void push_up(int id){
	tree[id].len=tree[lid].len+tree[rid].len;
	tree[id].shu.resize(tree[id].len+2,inf),tree[id].shu[0]=-inf;
	tree[id].sum=tree[lid].sum+tree[rid].sum;
	int ll1=0;
	for(int i=0;i<=tree[lid].len;i++){
		if(ll1>tree[rid].len){
			ll1--;
		}
		for(;ll1<=tree[rid].len;ll1++){
			ll v1=tree[rid].shu[ll1]+i*modd-tree[lid].sum;
			if(v1>=tree[lid].shu[i+1]){
				ll1--;
				break;
			}
			tree[id].shu[i+ll1]=min(tree[id].shu[i+ll1],max(tree[lid].shu[i],v1));
		}
	}
	return;
}
inline ll query(int q,int w,ll qw){
	tp=0;
	for(q=q+nn-1,w=w+nn+1;q^w^1;q>>=1,w>>=1){
		if(~q&1){
			int pos=upper_bound(tree[q^1].shu.begin(),tree[q^1].shu.end(),qw)-tree[q^1].shu.begin()-1;
			qw=qw+tree[q^1].sum-pos*modd;
		}
		if(w&1){
			st[++tp]=w^1;
		}
	}
	for(int i=tp;i>=1;i--){
		int pos=upper_bound(tree[st[i]].shu.begin(),tree[st[i]].shu.end(),qw)-tree[st[i]].shu.begin()-1;
		qw=qw+tree[st[i]].sum-pos*modd;
	}
	return qw;
}
signed main(){
	n=read(),m=read(),modd=read();
	for(int i=1;i<=n;i++){
		a[i]=read();
	}
	nn=(1<<((int)log2(n)+1));
	for(int i=nn;i<(nn<<1);i++){
		tree[i].shu.resize(3);
		tree[i].sum=a[i-nn];
		tree[i].len=1;
		tree[i].shu[0]=-inf;
		tree[i].shu[1]=modd-a[i-nn];
		tree[i].shu[2]=inf;
	}
	for(int i=nn-1;i>=1;i--){
		push_up(i);
	}
	while(m--){
		x=read(),y=read(),z=read();
		x^=ans,y^=ans,z^=ans;
		ans=query(x,y,z);
		ans<0?(pc('-'),write(-ans)):write(ans);
		pc('\n'),ans=ans%n,ans=ans<0?ans+n:ans;
	}
	return 0;
}
posted @ 2025-07-23 09:13  特别之处  阅读(14)  评论(0)    收藏  举报