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;
}
浙公网安备 33010602011771号