1 条题解

  • 0
    @ 2026-5-8 20:38:30

    题意简化:给定一个序列,每次将一段区间加上一个等差数列或覆盖为一个等差数列,每次查询询问 llrr 之间最长等差数列有多长。

    因为等差数列公差相等,所以我们维护原序列的差分数组,每次查找就只需要找最长的相同连续子序列就可以了。我们可以用类似于最大子段和的方式维护,线段树记录区间最长,左端点最长,右端点最长,左端点的数,右端点的数,每次向上合并时维护就好了。

    代码

    码风较丑,勿怪。

    #include<bits/stdc++.h>
    using namespace std;
    #define N 300005
    #define intl long long
    #define inf (0x3f3f3f3f3f3f3f3f)
    #define For(i,a,b) for(intl i=a;i<=b;i++)
    #define deo(i,a,b) for(intl i=a;i>=b;i--)
    intl read() {
    	intl x=0,k=1;char ch=getchar();
    	while(!isdigit(ch)) {if(ch == '-') k=-1;ch=getchar();}
    	while(isdigit(ch)) {x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
    	return x*k;
    }
    intl a[N];
    struct Seg{
    	intl mx[N<<2], lmx[N<<2], rmx[N<<2], lv[N<<2], rv[N<<2], sum[N<<2], tag[N<<2], add[N<<2];
    	#define lc (p<<1)
    	#define rc (p<<1|1)
    	#define mid ((l+r)>>1)
    	void pushdown(intl p,intl l,intl r) {
    		if(tag[p] != -inf) {
    			lv[lc] = rv[lc] = lv[rc] = rv[rc] = tag[p];lmx[lc] = rmx[lc] = mx[lc] = mid-l+1;lmx[rc] = rmx[rc] = mx[rc] = r-mid;
    			sum[lc] = (mid-l+1)*tag[p], sum[rc] = (r-mid)*tag[p], tag[lc] = tag[p], tag[rc] = tag[p];
    			tag[p] = -inf;add[lc] = add[rc] = 0;
    		}
    		if(add[p]) {
    			lv[lc] += add[p], rv[lc] += add[p], lv[rc] += add[p], rv[rc] += add[p];
    			sum[lc] += (mid-l+1)*add[p], sum[rc] += (r-mid)*add[p], add[lc] += add[p], add[rc] += add[p];
    			add[p] = 0; 
    		}
    	}
    	void build(intl p,intl l,intl r) {
    		tag[p] = -inf;
    		if(l == r) return mx[p] = lmx[p] = rmx[p] = 1, lv[p] = rv[p] = sum[p] = a[l], void();
    		build(lc,l,mid), build(rc,mid+1,r);
    		mx[p] = max({mx[lc], mx[rc], lmx[rc] + (rv[lc] == lv[rc])*rmx[lc]});
    		lmx[p] = max(lmx[lc], (lmx[lc] == (mid-l+1) && rv[lc] == lv[rc])*(mid-l+1+lmx[rc])), rmx[p] = max(rmx[rc], (rmx[rc] == (r-mid) && rv[lc] == lv[rc])*(r-mid+rmx[lc])), sum[p] = sum[lc] + sum[rc], lv[p] = lv[lc], rv[p] = rv[rc];
    	}
    	void updata(intl p,intl l,intl r,intl ll,intl rr,intl d, intl op) {
    		if(ll > rr) return ;
    		if(rr < l || r < ll) return ;
    		if(ll <= l && r <= rr) {
    			if(!op) add[p] += d, lv[p] += d, rv[p] += d, sum[p] += (r-l+1)*d;
    			else tag[p] = d, sum[p] = (r-l+1)*d, lv[p] = rv[p] = d, lmx[p] = rmx[p] = mx[p] = r-l+1, add[p] = 0;
    			return ;
    		}
    		pushdown(p,l,r);
    		updata(lc,l,mid,ll,rr,d,op), updata(rc,mid+1,r,ll,rr,d,op);
    		sum[p] = sum[lc] + sum[rc], lv[p] = lv[lc], rv[p] = rv[rc];			
    		mx[p] = max({mx[lc], mx[rc], lmx[rc] + (rv[lc] == lv[rc])*rmx[lc]});
    		lmx[p] = max(lmx[lc], (lmx[lc] == (mid-l+1) && rv[lc] == lv[rc])*(mid-l+1+lmx[rc]));
    		rmx[p] = max(rmx[rc], (rmx[rc] == (r-mid) && rv[lc] == lv[rc])*(r-mid+rmx[lc]));
    	}
    	struct node{
    		intl mx,lmx,rmx,lv,rv;
    	};
    	node query(intl p,intl l,intl r,intl ll,intl rr) {
    		if(ll > rr) return {0ll,0ll,0ll,0ll,0ll};
    		if(rr < l || r < ll) return {-inf,-inf,-inf,-inf,-inf};
    		if(ll <= l && r <= rr) return {mx[p], lmx[p], rmx[p], lv[p], rv[p]};
    		pushdown(p,l,r);
    		node tmp1=query(lc,l,mid,ll,rr), tmp2 = query(rc,mid+1,r,ll,rr);
    		if(tmp1.mx == -inf) return tmp2;
    		if(tmp2.mx == -inf) return tmp1;
    		node ans = {max({tmp1.mx,tmp2.mx,tmp1.rmx+(tmp1.rv == tmp2.lv)*tmp2.lmx}),max(tmp1.lmx, (tmp1.lmx == (mid-l+1)&&(tmp1.rv == tmp2.lv))*(mid-l+1+tmp2.lmx)),max(tmp2.rmx, (tmp2.rmx == (r-mid)&&(tmp1.rv == tmp2.lv))*(r-mid+tmp1.rmx)),tmp1.lv,tmp2.rv}; 
    		return ans;
    	}
    	intl Sum(intl p,intl l,intl r,intl ll,intl rr){
    		if(ll > rr) return 0ll;
    		if(rr < l || r < ll) return 0ll;
    		if(ll <= l && r <= rr) return sum[p];
    		pushdown(p,l,r);
    		return Sum(lc,l,mid,ll,rr) + Sum(rc,mid+1,r,ll,rr);
    	}
    }seg;
    intl n, q;
    int main() {
    	n = read(), q = read();
    	For(i,1,n) a[i] = read();
    	deo(i,n,1) a[i] = a[i]-a[i-1];
    	seg.build(1,1,n);
    	while(q--) {
    		intl op = read();
    		if(op == 1) {
    			intl l = read(), r = read(), s = read(), c = read();
    			intl tmp = seg.Sum(1,1,n,1,r+1);
    			seg.updata(1,1,n,l+1,r,c,0), seg.updata(1,1,n,l,l,s,0);
    			if(r+1 <= n) seg.updata(1,1,n,r+1,r+1,tmp - seg.Sum(1,1,n,1,r),1);
    			
    		} else if(op == 2) {
    			intl l = read(), r = read(), s = read(), c = read();
    			intl tmp = s - seg.Sum(1,1,n,1,l-1),  tmp2 = seg.Sum(1,1,n,1,r+1);
    			seg.updata(1,1,n,l,l,tmp,1);
    			seg.updata(1,1,n,l+1,r,c,1);
    			if(r+1 <= n) seg.updata(1,1,n,r+1,r+1,tmp2-seg.Sum(1,1,n,1,r),1);
    		} else {
    			intl l = read(), r =read();
    			printf("%lld\n", seg.query(1,1,n,l+1,r).mx+1);
    		}
    	} 
    	return 0;
    }
    
    
    • 1

    信息

    ID
    10990
    时间
    3000ms
    内存
    1024MiB
    难度
    10
    标签
    递交数
    1
    已通过
    1
    上传者