題目:給定n個數,m個操作,每次給一段區間加一個等差數列或者詢問一段區間至少要用多少個等差數列來表示。$n,m\leqslant 10^{5}$
題解:老套路,維護差分數組,修改操作變成了兩個單點加和一個區間加。然后我們用線段樹維護,合並答案的時候復雜一點,s[0/1][0/1]表示左右端點取不取的答案就行啦。
#include<iostream> #include<cstdio> #define MN 100000 using namespace std; inline int read() { int x = 0 , f = 1; char ch = getchar(); while(ch < '0' || ch > '9'){ if(ch == '-') f = -1; ch = getchar();} while(ch >= '0' && ch <= '9'){x = x * 10 + ch - '0';ch = getchar();} return x * f; } int n,q,s[MN+5]; char op[4]; inline void re(int&x,int y){if(y<x) x=y;} struct data { int s[4],l,r; data operator + (data y) { data c;c.l=l;c.r=y.r; c.s[0]=s[2]+y.s[1]-(r==y.l); re(c.s[0],s[0]+y.s[1]);re(c.s[0],s[2]+y.s[0]); c.s[1]=s[3]+y.s[1]-(r==y.l); re(c.s[1],s[1]+y.s[1]);re(c.s[1],s[3]+y.s[0]); c.s[2]=s[2]+y.s[3]-(r==y.l); re(c.s[2],s[2]+y.s[2]);re(c.s[2],s[0]+y.s[3]); c.s[3]=s[3]+y.s[3]-(r==y.l); re(c.s[3],s[3]+y.s[2]);re(c.s[3],s[1]+y.s[3]); return c; } }; struct node{ int l,r,val;data x; }T[MN*4+5]; void pushdown(int x) { int l=x<<1,r=x<<1|1; T[l].val+=T[x].val;T[r].val+=T[x].val; T[l].x.l+=T[x].val;T[l].x.r+=T[x].val; T[r].x.l+=T[x].val;T[r].x.r+=T[x].val; T[x].val=0; } void build(int x,int l,int r) { if((T[x].l=l)==(T[x].r=r)) { T[x].x.s[0]=0;T[x].x.l=T[x].x.r=s[l]; T[x].x.s[1]=T[x].x.s[3]=T[x].x.s[2]=1; return; } int mid=l+r>>1; build(x<<1,l,mid);build(x<<1|1,mid+1,r); T[x].x=T[x<<1].x+T[x<<1|1].x; } data query(int x,int l,int r) { //cout<<"query"<<x<<" "<<l<<" "<<r<<" "<<T[x].l<<" "<<T[x].r<<endl; if(T[x].l==l&&T[x].r==r) return T[x].x; if(T[x].val) pushdown(x); int mid=T[x].l+T[x].r>>1; if(r<=mid) return query(x<<1,l,r); else if(l>mid) return query(x<<1|1,l,r); else return query(x<<1,l,mid)+query(x<<1|1,mid+1,r); } void modify(int x,int l,int r,int ad) { if(T[x].l==l&&T[x].r==r) { T[x].val+=ad;T[x].x.l+=ad;T[x].x.r+=ad; return; } if(T[x].val) pushdown(x); int mid=T[x].l+T[x].r>>1; if(r<=mid) modify(x<<1,l,r,ad); else if(l>mid) modify(x<<1|1,l,r,ad); else modify(x<<1,l,mid,ad),modify(x<<1|1,mid+1,r,ad); T[x].x=T[x<<1].x+T[x<<1|1].x; } int main() { n=read(); for(int i=1;i<=n;i++) s[i]=read(); for(int i=1;i<n;i++) s[i]=s[i+1]-s[i]; build(1,1,n-1); for(q=read();q;q--) { scanf("%s",op);int l=read(),r=read(); if(op[0]=='B') l==r?puts("1"):printf("%d\n",query(1,l,r-1).s[3]); else { int a=read(),b=read(); if(l!=1) modify(1,l-1,l-1,a); if(l!=r) modify(1,l,r-1,b); if(r!=n) modify(1,r,r,-(a+(r-l)*b)); } } return 0; }