# BZOJ 2138: stone Hall定理 线段树

## 2138: stone

Time Limit: 10 Sec  Memory Limit: 259 MB
Submit: 130  Solved: 53
[Submit][Status][Discuss]

5
3 2 4 7
3
2 5 2 6 4 9
2 4
1 2
3 5

## Sample Output

2
5
5
【样例说明】

【数据范围】
100% N<=40000 M<=N 1<=L[i]<=R[i]<=N A[i]<=500

#include<cmath>
#include<ctime>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<complex>
#include<iostream>
#include<algorithm>
#include<iomanip>
#include<vector>
#include<string>
#include<bitset>
#include<queue>
#include<map>
#include<set>
using namespace std;

typedef long long ll;

{
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch<='9'&&ch>='0'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
return x*f;
}
void print(int x)
{if(x<0)putchar('-'),x=-x;if(x>=10)print(x/10);putchar(x%10+'0');}

const int N=40100;

struct seg_tree{int mx,mn,tagmx,tagmn;}tr[N<<2];

int n,K[N],a[N];

inline void pushup(int k)
{tr[k].mx=max(tr[k<<1].mx,tr[k<<1|1].mx);tr[k].mn=min(tr[k<<1].mn,tr[k<<1|1].mn);}

inline void pushdown(int k)
{
if(tr[k].tagmn)
{
int tmp=tr[k].tagmn;
tr[k].tagmn=0;
tr[k<<1].tagmn+=tmp;tr[k<<1].mn+=tmp;
tr[k<<1|1].tagmn+=tmp;tr[k<<1|1].mn+=tmp;
}
if(tr[k].tagmx)
{
int tmp=tr[k].tagmx;
tr[k].tagmx=0;
tr[k<<1].tagmx+=tmp;tr[k<<1].mx+=tmp;
tr[k<<1|1].tagmx+=tmp;tr[k<<1|1].mx+=tmp;
}
}

void build(int k,int l,int r)
{
if(l==r){tr[k].mx=tr[k].mn=a[l];return ;}
int mid=(l+r)>>1;
build(k<<1,l,mid);build(k<<1|1,mid+1,r);
pushup(k);
}

void modify_mn(int k,int l,int r,int x,int y,int val)
{
if(l>=x&&r<=y){tr[k].mn+=val;tr[k].tagmn+=val;return ;}
int mid=(l+r)>>1;pushdown(k);
if(x<=mid)modify_mn(k<<1,l,mid,x,y,val);
if(y>mid)modify_mn(k<<1|1,mid+1,r,x,y,val);
pushup(k);
}

void modify_mx(int k,int l,int r,int x,int y,int val)
{
if(l>=x&&r<=y){tr[k].mx+=val;tr[k].tagmx+=val;return ;}
int mid=(l+r)>>1;pushdown(k);
if(x<=mid)modify_mx(k<<1,l,mid,x,y,val);
if(y>mid)modify_mx(k<<1|1,mid+1,r,x,y,val);
pushup(k);
}

int query_mn(int k,int l,int r,int x,int y)
{
if(x>y)return 0;
if(l>=x&&r<=y)return tr[k].mn;
int mid=(l+r)>>1;pushdown(k);
if(x>mid)return query_mn(k<<1|1,mid+1,r,x,y);
else if(y<=mid)return query_mn(k<<1,l,mid,x,y);
else return min(query_mn(k<<1|1,mid+1,r,x,y),query_mn(k<<1,l,mid,x,y));
}

int query_mx(int k,int l,int r,int x,int y)
{
if(x>y)return 0;
if(l>=x&&r<=y)return tr[k].mx;
int mid=(l+r)>>1;pushdown(k);
if(x>mid)return query_mx(k<<1|1,mid+1,r,x,y);
else if(y<=mid)return query_mx(k<<1,l,mid,x,y);
else return max(query_mx(k<<1|1,mid+1,r,x,y),query_mx(k<<1,l,mid,x,y));
}

int main()
{
for(i=1;i<=n;++i)a[i]=a[i-1]+(1ll*(i-x)*(i-x)+1ll*(i-y)*(i-y)+1ll*(i-z)*(i-z))%P;
build(1,0,n);
for(i=3;i<=m;++i)K[i]=(1ll*x*K[i-1]+1ll*y*K[i-2]+z)%P;
for(i=1;i<=m;++i)
{
res=min(query_mn(1,0,n,r,n)-query_mx(1,0,n,0,l-1),K[i]);
modify_mx(1,0,n,l,n,-res);modify_mn(1,0,n,r,n,-res);
print(res);puts("");
}
return 0;
}
/*
5
3 2 4 7
3
2 5 2 6 4 9
2 4
1 2
3 5

2
5
5
*/