给包含n个数的初始序列,A[1], A[2], ..., A[n]。
给q多个操作,操作如下:
1 a b v, 把[a, b] 的值改为v,即A[a] = A[a+1] = ... = A[b] = v。
2 a b, 查询[a, b] 之间的相同数的连续和最大值。
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define havemid int m=(l+r)>>1
#define left (rt<<1)
#define right (rt<<1|1)
const int maxn=100010;
int lva[maxn<<2]; // 最左面的值
int rva[maxn<<2]; // 最右面的值
int lnum[maxn<<2]; // 最左面的数的个数
int rnum[maxn<<2]; // 最右面的数的个数
int mov[maxn<<2]; // 区间最大连续值
int add[maxn<<2]; // 延迟标记
int va[maxn];
void pushup(int l,int r,int rt){
havemid;
lva[rt]=lva[left]; //父节点的左值=左儿子左值
rva[rt]=rva[right]; //右
lnum[rt]=lnum[left]; //父节点的左连续个数=左儿子左连续个数
rnum[rt]=rnum[right]; //右
mov[rt]=max(mov[left],mov[right]); //区间最值=左区间最值和右区间中的最大
if(lva[left]==lva[right]&&lnum[left]==m-l+1)lnum[rt]+=lnum[right];
//左区间左值=右区间左值&&左区间左连续充满做区间,父区间左连续就可以+上右区间左连续
if(rva[right]==rva[left]&&rnum[right]==r-m)rnum[rt]+=rnum[left];
if(rva[left]==lva[right])mov[rt]=max(mov[rt],rva[left]*(rnum[left]+lnum[right]));
//左区间右值=右区间左值 父节点最值和中间区间的最值比较 要最大的
}
void pushdown(int l,int r,int rt){
if(add[rt]!=-1){
havemid;
add[left]=add[right]=add[rt]; //延迟标记向下传递
lva[left]=lva[right]=rva[left]=rva[right]=add[rt]; //各种值都是add的值了
lnum[left]=rnum[left]=m-l+1; //连续的个数充满着整个区间
lnum[right]=rnum[right]=r-m;
mov[left]=(m-l+1)*add[rt]; //区间和最值为个数*变成的那个数
mov[right]=(r-m)*add[rt];
add[rt]=-1;
}
}
void build(int l,int r,int rt){
add[rt]=-1;
if(l==r){
scanf("%d",&va[l]);
lva[rt]=va[l]; //各种值为输入的那个值
rva[rt]=va[l];
mov[rt]=va[l];
lnum[rt]=rnum[rt]=1;//各种连续为一
return ;
}
havemid;
build(lson);
build(rson);
pushup(l,r,rt);
}
void update(int L,int R,int c,int l,int r,int rt){
if(L<=l&&r<=R){
add[rt]=c;
mov[rt]=(r-l+1)*c;
lva[rt]=rva[rt]=c;
lnum[rt]=rnum[rt]=r-l+1;
return ;
}
pushdown(l,r,rt);
havemid;
if(L<=m)update(L,R,c,lson);
if(R>m)update(L,R,c,rson);
pushup(l,r,rt);
}
int query(int L,int R,int l,int r,int rt){
if(L<=l&&r<=R){
return mov[rt];
}
havemid;
pushdown(l,r,rt);
if(R<=m)return query(L,R,lson);
else if(L>m)return query(L,R,rson);
else {
int tmp=0;
if(rva[left]==lva[right]) //左的右值和右的左值相等 就可以合并
tmp=rva[left]*(min(rnum[left],m-L+1)+min(lnum[right],R-m));
//不能超出查询区间
int t1=query(L,R,lson);
int t2=query(L,R,rson);
int ret=max(tmp,max(t1,t2));
return ret;
}
}
int main(){
int n,m,op,a,b,c,ca=1;
while(scanf("%d",&n)!=EOF){
build(1,n,1);
scanf("%d",&m);
printf("Case %d:\n",ca++);
while(m--){
scanf("%d",&op);
if(op==1){
scanf("%d%d%d",&a,&b,&c);
update(a,b,c,1,n,1);
}
else {
scanf("%d%d",&a,&b);
int res=query(a,b,1,n,1);
printf("%d\n",res);
}
}
}
return 0;
}