卡死了好几天,最后居然是因为结构体里的布尔型变量自动初始值为true,太苦逼了些。。。
题目给定一些+的操作,在一个序列上加上另一个等差序列,最后让求最大的等差序列长度。
等差序列的特点就是相邻两项之差为定值,于是我们便可以用线段树记录每个点与之前一点的差值,然后每当来一个操作时要更新三次,分别是L+1~R上每两个数差值增加D(即新增加的等差序列差值),首项和之前一项的差值增加A,末项与其后一位的差值增加A+(R-L)*D,然后记录每个区间左端点为起点的最长长度和公差,右端点为终点的最长长度和公差,整个区间最长长度,一直维护此线段树即可。
查询时,加上区间合并的内容即可。
附代码:
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define delf int m=(l+r)>>1
const int MAX=100000+10;
long long int vv[MAX<<2]; //记录更新值
bool mark[MAX<<2]; //记录该点是否向下更新过
int sum[MAX<<2]; //记录整个区间最长等差序列长度
int le[MAX<<2]; //记录整个左孩子最长等差序列长度
int ri[MAX<<2]; //记录整个右孩子最长等差序列长度
long long int ld[MAX<<2]; //记录左孩子公差
long long int rd[MAX<<2]; //记录右孩子公差
bool m[MAX<<2]; //记录该区间是否整个区间都是等差序列
int ans;
int max(int a,int b)
{
return a>b?a:b;
}
void pushup(int rt)
{
sum[rt]=max(sum[rt<<1],sum[rt<<1|1]); //当前节点的最大值由其孩子中较大者决定
if (rd[rt<<1]==ld[rt<<1|1]) //如果左孩子右和右孩子左构成等差序列,更新sum
sum[rt]=max(sum[rt],ri[rt<<1]+le[rt<<1|1]);
ld[rt]=ld[rt<<1]; //初始化左端序列差
rd[rt]=rd[rt<<1|1]; //初始化右端序列差
le[rt]=le[rt<<1]; //初始化左端序列长
ri[rt]=ri[rt<<1|1]; //初始化右端序列长
if (m[rt<<1]&&ld[rt<<1]==ld[rt<<1|1]) //如果整个左孩子是一个等差序列且跟右孩子的左区间能合并,则合并
le[rt]=le[rt<<1]+le[rt<<1|1];
if (m[rt<<1|1]&&rd[rt<<1]==rd[rt<<1|1]) //如果整个右孩子是一个等差序列且跟左孩子的右区间能合并,则合并
ri[rt]=ri[rt<<1]+ri[rt<<1|1];
sum[rt]=max(sum[rt],le[rt]); //再次更新sum
sum[rt]=max(sum[rt],ri[rt]);
m[rt]=false;
if (m[rt<<1]&&m[rt<<1|1]&&ld[rt<<1]==rd[rt<<1|1]) //如果整个区间能连成一个等差序列,则连起来
m[rt]=true;
}
void pushdown(int rt)
{
if (mark[rt]==0) //如果没有可更新的内容,则返回
return ;
ld[rt<<1]+=vv[rt];
rd[rt<<1]+=vv[rt];
ld[rt<<1|1]+=vv[rt];
rd[rt<<1|1]+=vv[rt];
vv[rt<<1]+=vv[rt];
vv[rt<<1|1]+=vv[rt];
mark[rt<<1]=mark[rt<<1|1]=1;
mark[rt]=0;
vv[rt]=0;
return ;
}
void build(int l,int r,int rt)
{
sum[rt]=le[rt]=ri[rt]=ld[rt]=rd[rt]=m[rt]=vv[rt]=mark[rt]=0;
if (l==r)
{
sum[rt]=le[rt]=ri[rt]=1;
m[rt]=true;
return ;
}
delf;
build(lson);
build(rson);
pushup(rt);
return ;
}
void update(int L,int R,int d,int l,int r,int rt)
{
if (L>R)
return ;
//cout<<l<<" "<<r<<endl;
if (L<=l&&r<=R)
{
//cout<<l<<" AA "<<r<<" "<<rt<<endl;
vv[rt]+=d;
ld[rt]+=d;
rd[rt]+=d;
mark[rt]=1;
return ;
}
delf;
pushdown(rt);
if (L<=m)
update(L,R,d,lson);
if (R>m)
update(L,R,d,rson);
pushup(rt);
return ;
}
void update(int k,int v,int l,int r,int rt)
{
if (l==r)
{
vv[rt]+=v;
ld[rt]+=v;
rd[rt]+=v;
return ;
}
delf;
pushdown(rt);
if (k<=m)
update(k,v,lson);
else
update(k,v,rson);
pushup(rt);
return ;
}
struct pp
{
int ld,le,rd,ri;
bool m;
pp()
{
ld=le=rd=ri=0;
m=false;
}
};
pp query(int L,int R,int l,int r,int rt)
{
pp p;
if (L>R)
return p;
if (L<=l&&r<=R)
{
ans=max(ans,sum[rt]);
p.ld=ld[rt];
p.rd=rd[rt];
p.le=le[rt];
p.ri=ri[rt];
p.m=m[rt];
return p;
}
pushdown(rt);
delf;
pp p1,p2;
if (R<=m)
return query(L,R,lson);
else if (L>m)
return query(L,R,rson);
else if (L<=m&&R>m)
{
p1=query(L,R,lson);
p2=query(L,R,rson);
if (p1.rd==p2.ld)
ans=max(ans,p1.ri+p2.le);
p.ld=p1.ld;
p.rd=p2.rd;
p.le=p1.le;
p.ri=p2.ri;
if (p1.m&&p1.ld==p2.ld)
p.le=p1.le+p2.le;
if (p2.m&&p1.rd==p2.rd)
p.ri=p1.ri+p2.ri;
if (p1.m&&p2.m&&p1.ld==p2.rd)
p.m=true;
ans=max(ans,p.le);
ans=max(ans,p.ri);
//cout<<l<<" "<<r<<" "<<ans<<endl;
return p;
}
}
int main()
{
int n,m,i=0;
while (cin>>n>>m)
{
build(0,n-1,1);
i++;
printf("Case #%d:\n",i);
while (m--)
{
char s[10];
scanf("%s",s);
if (s[0]=='A')
{
int l,r,a,d;
scanf("%d%d%d%d",&l,&r,&a,&d);
update(l+1,r,d,0,n-1,1); //新更新的范围内的两数之差要变
if (r<n-1)
update(r+1,-(a+(r-l)*d),0,n-1,1); //新更新区间右部第一个与区间末尾的差要变
update(l,a,0,n-1,1); //新更新区间左部第一个和区间首个的差要变
}
else
{
int l,r;
ans=0;
scanf("%d%d",&l,&r);
query(l+1,r,0,n-1,1);
printf("%d\n",ans+1);
}
}
}
}