思路
对于这题,首先要知道维护一些什么东西.
我们都知道区间加个等差数列,假如维护单点求和的话,直接维护公差即可.因为区间加一个等差数列只需要两次单点修改和一次区间修改即可.
对于这题,我们很容易想到维护公差.但是对于查询操作维护公差是远远不够的.每次是询问你区间中有多少个等差数列.对于这个查询啊,我们假如线段树维护的是公差的话,我们很容易想到公差相等的一定是属于一个等差数列,但是!我们维护的是公差对吧,公差不相等它也可能是一个等差数列.
列如:
原数组[1 2 3 6 11 16]. 公差数组[1 1 3 5 5].
显然这个答案是2的.
所以我们需要维护的信息需要加一些.
我们不妨设为cl,cr,clr,nlr,lval,rval. 分别表示为[l,r),(l,r],[l,r],(l,r)的答案最小值.左端点的价值,右端点的价值.
然后转移下这些信息就是答案了~这题就解决了...
这里写下这个的转移.
tr[u].lval=tr[u<<1].lval,tr[u].rval=tr[u<<1|1].rval; tr[u].cl=tr[u<<1].clr+tr[u<<1|1].cl-(tr[u<<1].rval==tr[u<<1|1].lval); tr[u].cl=min(tr[u].cl,min(tr[u<<1].cl+tr[u<<1|1].cl,tr[u<<1].clr+tr[u<<1|1].nlr)); tr[u].cr=tr[u<<1].cr+tr[u<<1|1].clr-(tr[u<<1].rval==tr[u<<1|1].lval); tr[u].cr=min(tr[u].cr,min(tr[u<<1].cr+tr[u<<1|1].cr,tr[u<<1].nlr+tr[u<<1|1].clr)); tr[u].clr=tr[u<<1].clr+tr[u<<1|1].clr-(tr[u<<1].rval==tr[u<<1|1].lval); tr[u].clr=min(tr[u].clr,min(tr[u<<1].clr+tr[u<<1|1].cr,tr[u<<1].cl+tr[u<<1|1].clr)); tr[u].nlr=tr[u<<1].cr+tr[u<<1|1].cl-(tr[u<<1].rval==tr[u<<1|1].lval); tr[u].nlr=min(tr[u].nlr,min(tr[u<<1].nlr+tr[u<<1|1].cl,tr[u<<1].cr+tr[u<<1|1].nlr));
还挺多的...
代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e5+5;
struct Tree{
ll l,r,lval,rval,cl,cr,clr,nlr,lazy;
}tr[N<<2];
ll v[N];
void pushup(ll u)
{
tr[u].lval=tr[u<<1].lval,tr[u].rval=tr[u<<1|1].rval;
tr[u].cl=tr[u<<1].clr+tr[u<<1|1].cl-(tr[u<<1].rval==tr[u<<1|1].lval);
tr[u].cl=min(tr[u].cl,min(tr[u<<1].cl+tr[u<<1|1].cl,tr[u<<1].clr+tr[u<<1|1].nlr));
tr[u].cr=tr[u<<1].cr+tr[u<<1|1].clr-(tr[u<<1].rval==tr[u<<1|1].lval);
tr[u].cr=min(tr[u].cr,min(tr[u<<1].cr+tr[u<<1|1].cr,tr[u<<1].nlr+tr[u<<1|1].clr));
tr[u].clr=tr[u<<1].clr+tr[u<<1|1].clr-(tr[u<<1].rval==tr[u<<1|1].lval);
tr[u].clr=min(tr[u].clr,min(tr[u<<1].clr+tr[u<<1|1].cr,tr[u<<1].cl+tr[u<<1|1].clr));
tr[u].nlr=tr[u<<1].cr+tr[u<<1|1].cl-(tr[u<<1].rval==tr[u<<1|1].lval);
tr[u].nlr=min(tr[u].nlr,min(tr[u<<1].nlr+tr[u<<1|1].cl,tr[u<<1].cr+tr[u<<1|1].nlr));
}
void pushdown(ll u)
{
if(tr[u].lazy)
{
tr[u<<1].lazy+=tr[u].lazy;
tr[u<<1|1].lazy+=tr[u].lazy;
tr[u<<1].lval+=tr[u].lazy;
tr[u<<1|1].lval+=tr[u].lazy;
tr[u<<1].rval+=tr[u].lazy;
tr[u<<1|1].rval+=tr[u].lazy;
tr[u].lazy=0;
}
}
void add(ll u,ll l,ll r,ll val)
{
if(l>tr[u].r||r<tr[u].l) return;
if(l<=tr[u].l&&r>=tr[u].r)
{
tr[u].lazy+=val;
tr[u].lval+=val;
tr[u].rval+=val;
return;
}
pushdown(u);
add(u<<1,l,r,val);
add(u<<1|1,l,r,val);
pushup(u);
}
Tree query(ll u,ll l,ll r);
Tree marge(ll u,ll l,ll r)
{
Tree res;
Tree L=query(u<<1,l,r);
Tree R=query(u<<1|1,l,r);
res.l=L.l,res.r=R.r,res.lval=L.lval,res.rval=R.rval;
res.cl=L.clr+R.cl-(L.rval==R.lval);
res.cl=min(res.cl,min(L.cl+R.cl,L.clr+R.nlr));
res.cr=L.cr+R.clr-(L.rval==R.lval);
res.cr=min(res.cr,min(L.cr+R.cr,L.nlr+R.clr));
res.clr=L.clr+R.clr-(L.rval==R.lval);
res.clr=min(res.clr,min(L.clr+R.cr,L.cl+R.clr));
res.nlr=L.cr+R.cl-(L.rval==R.lval);
res.nlr=min(res.nlr,min(L.nlr+R.cl,L.cr+R.nlr));
return res;
}
Tree query(ll u,ll l,ll r)
{
if(l<=tr[u].l&&r>=tr[u].r) return tr[u];
pushdown(u);
ll mid=(tr[u].l+tr[u].r)>>1;
if(r<=mid) return query(u<<1,l,r);
if(l>mid) return query(u<<1|1,l,r);
return marge(u,l,r);
}
void build(ll u,ll l,ll r)
{
tr[u].l=l,tr[u].r=r;
if(l==r)
{
tr[u].lval=tr[u].rval=v[l];
tr[u].cl=tr[u].cr=tr[u].clr=1;
return;
}
int mid=(l+r)>>1;
build(u<<1,l,mid);
build(u<<1|1,mid+1,r);
pushup(u);
}
int main()
{
ll n;
scanf("%lld",&n);
for(int i=1;i<=n;i++) scanf("%lld",&v[i]);
for(int i=1;i<n;i++) v[i]=v[i+1]-v[i];
build(1,1,n-1);
ll Q;
scanf("%lld",&Q);
while(Q--)
{
char c;
cin>>c;
if(c=='A')
{
ll s,t,a,b;
scanf("%lld%lld%lld%lld",&s,&t,&a,&b);
//s-1 [s,t-1] t
if(s!=1) add(1,s-1,s-1,a);
if(t!=n) add(1,t,t,-(a+b*(t-s)));
if(s!=t) add(1,s,t-1,b);
}
else
{
ll s,t;
scanf("%lld%lld",&s,&t);
if(s==t) puts("1");
else printf("%lld\n",query(1,s,t-1).clr);
}
}
return 0;
}
京公网安备 11010502036488号