1 条题解
-
0
题意简化:给定一个序列,每次将一段区间加上一个等差数列或覆盖为一个等差数列,每次查询询问 到 之间最长等差数列有多长。
因为等差数列公差相等,所以我们维护原序列的差分数组,每次查找就只需要找最长的相同连续子序列就可以了。我们可以用类似于最大子段和的方式维护,线段树记录区间最长,左端点最长,右端点最长,左端点的数,右端点的数,每次向上合并时维护就好了。
代码
码风较丑,勿怪。
#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
- 上传者