picks loves segment tree I
阿新 • • 發佈:2018-10-13
mes sunshine ron max pick def print tex strong
picks loves segment tree I
題目背景
來源:
\(\text {2018 WC Segment Tree Beats}\)
原作者:
\(\text {C_SUNSHINE}\)
\(\text {jiry_2}\)
題目描述:
- 給定一個長度為\(n\)的數列\(A\),接下來有\(m\)次操作:
- 區間\([l,r]\)中的所有數變成\(min(A_i,x)\)
- 詢問區間\([l,r]\)中所有數的和
- \(n,m \le 50000\)
- 我會分塊!
- \(n,m \le 500000\)
- 線段樹?
輸入輸出格式
輸入格式
第一行兩個正整數表示\(N,M\)
第二行\(N\)個正整數,表示數列\(A_i\)
接下來\(M\)行每行包含\(3\)或\(4\)個整數,表示一個操作,具體如下:
操作1: 1 x y x
含義:將區間\([l,r]\)內每個數變成\(min(A_i,x)\)
操作2: 2 x y
含義:輸出區間\([l,r]\)內每個數的和
輸出格式
輸出包含若幹行整數,即為所有操作\(2\)的結果。
說明:
對於所有的數據,有\(N \le 500000,M \le 500000,a_i \le 2 \times 10^9\)
保證所有出現的數據在\(int64/long \ long\)範圍內
本菜雞說不清楚,直接當板子了,看網上的dalao們都寫的Ⅴ,Ⅵ,Ⅶ,Ⅸ什麽的,我太菜,從基礎開始來吧。
Code:
#include <cstdio> #define ll long long #define ls id<<1 #define rs id<<1|1 const int N=5e5+10; ll mx[N<<2],se[N<<2],sum[N<<2],tag[N<<2],a[N]; ll max(ll x,ll y){return x>y?x:y;} int cnt[N<<2],n,m; void updata(int id) { if(mx[ls]>mx[rs]) { mx[id]=mx[ls]; cnt[id]=cnt[ls]; se[id]=max(se[ls],mx[rs]); } else if(mx[ls]<mx[rs]) { mx[id]=mx[rs]; cnt[id]=cnt[rs]; se[id]=max(mx[ls],se[rs]); } else { mx[id]=mx[ls]; cnt[id]=cnt[ls]+cnt[rs]; se[id]=max(se[ls],se[rs]); } sum[id]=sum[ls]+sum[rs]; } void build(int id,int l,int r) { if(l==r) { sum[id]=mx[id]=a[l]; cnt[id]=1; se[id]=0; return; } int mid=l+r>>1; build(ls,l,mid),build(rs,mid+1,r); updata(id); } void pushdown(int id) { if(tag[id]) { if(mx[ls]>tag[id]) { sum[ls]-=(mx[ls]-tag[id])*cnt[ls]; tag[ls]=mx[ls]=tag[id]; } if(mx[rs]>tag[id]) { sum[rs]-=(mx[rs]-tag[id])*cnt[rs]; tag[rs]=mx[rs]=tag[id]; } tag[id]=0; } } void change(int id,int L,int R,int l,int r,ll x) { if(mx[id]<=x) return; if(L==l&&R==r&&se[id]<x) { sum[id]-=(mx[id]-x)*cnt[id]; tag[id]=mx[id]=x; return; } pushdown(id); int Mid=L+R>>1; if(r<=Mid) change(ls,L,Mid,l,r,x); else if(l>Mid) change(rs,Mid+1,R,l,r,x); else change(ls,L,Mid,l,Mid,x),change(rs,Mid+1,R,Mid+1,r,x); updata(id); } ll query(int id,int L,int R,int l,int r) { if(l==L&&r==R) return sum[id]; pushdown(id); int Mid=L+R>>1; if(r<=Mid) return query(ls,L,Mid,l,r); else if(l>Mid) return query(rs,Mid+1,R,l,r); else return query(ls,L,Mid,l,Mid)+query(rs,Mid+1,R,Mid+1,r); } int main() { scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) scanf("%lld",a+i); build(1,1,n); ll x; for(int op,l,r,i=1;i<=m;i++) { scanf("%d%d%d",&op,&l,&r); if(op==1) { scanf("%lld",&x); change(1,1,n,l,r,x); } else printf("%lld\n",query(1,1,n,l,r)); } return 0; }
2018.10.13
picks loves segment tree I