题面
http://darkbzoj.tk/problem/2138
题解
用类前缀和维护在给定的区间内的所有区间的价值之和,再用线段树维护区间最值。
把求全局最值转换成求当前区间左右最值那一步非常妙,是为了求出这块区域最多能被拿走多少块石子。
#include<stack>
#include<queue>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#define N 45000
#define ri register int
using namespace std;
int a[N],k[N],sum[N];
int n,m;
inline int read() {
int ret=0,f=0; char ch=getchar();
while (ch<'0' || ch>'9') f|=(ch=='-'),ch=getchar();
while (ch>='0' && ch<='9') ret*=10,ret+=(ch-'0'),ch=getchar();
return f?-ret:ret;
}
int sqr(int x) {
return x*x;
}
struct segment_tree {
int t1[N<<2],t2[N<<2];
int tag1[N<<2],tag2[N<<2];
void maketree(int x,int l,int r) {
if (l==r) {
t1[x]=t2[x]=sum[l];
return;
}
int mid=(l+r)/2;
maketree(x<<1,l,mid); maketree(x<<1|1,mid+1,r);
t1[x]=max(t1[x<<1],t1[x<<1|1]);
t2[x]=min(t2[x<<1],t2[x<<1|1]);
}
void pushdown1(int x) {
int k=tag1[x]; tag1[x]=0;
t1[x<<1]+=k; tag1[x<<1]+=k;
t1[x<<1|1]+=k; tag1[x<<1|1]+=k;
}
void pushdown2(int x) {
int k=tag2[x]; tag2[x]=0;
t2[x<<1]+=k; tag2[x<<1]+=k;
t2[x<<1|1]+=k; tag2[x<<1|1]+=k;
}
void modify1(int x,int lb,int rb,int l,int r,int k) {
if (l<=lb && rb<=r) {
t1[x]+=k; tag1[x]+=k;
return;
}
if (l>rb || r<lb) return;
pushdown1(x);
int mid=(lb+rb)/2;
modify1(x<<1,lb,mid,l,r,k); modify1(x<<1|1,mid+1,rb,l,r,k);
t1[x]=max(t1[x<<1],t1[x<<1|1]);
}
void modify2(int x,int lb,int rb,int l,int r,int k) {
if (l<=lb && rb<=r) {
t2[x]+=k; tag2[x]+=k;
return;
}
if (l>rb || r<lb) return;
pushdown2(x);
int mid=(lb+rb)/2;
modify2(x<<1,lb,mid,l,r,k); modify2(x<<1|1,mid+1,rb,l,r,k);
t2[x]=min(t2[x<<1],t2[x<<1|1]);
}
int query1(int x,int lb,int rb,int l,int r) {
if (l<=lb && rb<=r) return t1[x];
if (l>rb || r<lb) return -1e9;
pushdown1(x);
int mid=(lb+rb)/2;
return max(query1(x<<1,lb,mid,l,r),query1(x<<1|1,mid+1,rb,l,r));
}
int query2(int x,int lb,int rb,int l,int r) {
if (l<=lb && rb<=r) return t2[x];
if (l>rb || r<lb) return 1e9;
pushdown2(x);
int mid=(lb+rb)/2;
return min(query2(x<<1,lb,mid,l,r),query2(x<<1|1,mid+1,rb,l,r));
}
} T;
int main() {
n=read();
int x=read(),y=read(),z=read(),p=read();
for (ri i=1;i<=n;i++) a[i]=(sqr(i-x)+sqr(i-y)+sqr(i-z))%p;
m=read();
k[1]=read(); k[2]=read(); x=read(),y=read(),z=read(),p=read();
for (ri i=3;i<=m;i++) k[i]=(x*k[i-1]+y*k[i-2]+z)%p;
for (ri i=1;i<=n;i++) sum[i]=sum[i-1]+a[i];
T.maketree(1,1,n);
for (ri i=1;i<=m;i++) {
int l=read(),r=read();
k[i]=min(k[i],T.query2(1,1,n,r,n)-max(T.query1(1,1,n,1,l-1),0));
printf("%d\n",k[i]);
T.modify1(1,1,n,l,n,-k[i]); T.modify2(1,1,n,r,n,-k[i]);
}
return 0;
}
来源:https://www.cnblogs.com/shxnb666/p/11323893.html