1010 区区区间 分块 线段树
链接:https://ac.nowcoder.com/acm/contest/26896/1010
来源:牛客网
题目描述
KevenKevenKeven 特别喜欢线段树,他给你一个长度为 nnn 的序列,对序列进行mmm 次操作。
操作有两种:
1 l r k1\ l\ r\ k1 l r k :表示将下标在 [l,r][l , r][l,r] 区间内的数字替换成 [k,k+1,…,k+r−l][k,k+1,…,k+r-l][k,k+1,…,k+r−l]
2 l r2\ l\ r2 l r :表示查询区间 [l,r][l , r][l,r] 的区间和
输入描述:
第一行两个整数 n、mn、mn、m,表示序列的长度和操作次数(1<=n,m<=2e5)(1<=n,m<=2e5)(1<=n,m<=2e5)
第二行 nnn 个整数,表示序列的初始值 a1,a2,…an(1<=ai<=2e5)a_1,a_2,…a_n(1<=a_i<=2e5)a1,a2,…an(1<=ai<=2e5)
接下来 mmm 行,每行三或四个数字,若第一个数字是 111,则表示操作 111,反之则表示操作 222。
(1<=l<=r<=n,1<=k<=2e5)(1<=l<=r<=n,1<=k<=2e5)(1<=l<=r<=n,1<=k<=2e5)
输出描述:
对于每个操作 222,输出一行一个整数表示区间和。
分析
问题在于修改区间内的每一个位置的值不是统一的加减,而是有公差的。
可以用lazy 标记维护每个区间的首项,由于公差是固定的,也就知道了区间的尾项,传递下去的时候,也就知道了每一个位置的值。
//-------------------------代码---------------------------- #define int ll const int N = 2e5+10; int n,m; struct node { int l,r,s,la; } tr[N<<2]; int a[N]; void push_up(int u) { tr[u].s=tr[ul].s+tr[ur].s; } void push_down(int u) { if(tr[u].la==0)return ; tr[ul].la=tr[u].la;tr[ur].la=tr[u].la+tr_len(ul); int w=(tr[ul].r-tr[ul].l)+tr[ul].la; tr[ul].s=(tr[ul].la+w)*tr_len(ul)/2; tr[ur].s=tr[u].s-tr[ul].s; tr[u].la=0; } void build(int u,int l,int r) { tr[u]={l,r,0,0}; if(l==r){tr[u].s=a[l];return ;} build(ul,l,tr_mid);build(ur,tr_mid+1,r); push_up(u); } void modify(int u,int l,int r,int k) { if(tr[u].l>=l&&tr[u].r<=r) { tr[u].la=k+(tr[u].l-l);//la维护首项 int w=(tr[u].r-tr[u].l)+tr[u].la;//尾项 tr[u].s=(tr[u].la+w)*(tr_len(u))/2; return ; } push_down(u); if(l<=tr_mid)modify(ul,l,r,k); if(r>tr_mid)modify(ur,l,r,k); push_up(u); } int query(int u,int l,int r) { if(tr[u].l>=l&&tr[u].r<=r)return tr[u].s; if(tr[u].l>r||tr[u].r<l)return 0; push_down(u); return query(ul,l,r)+query(ur,l,r); } void solve() { cin>>n>>m; fo(i,1,n) cin>>a[i]; build(1,1,n); while(m -- ) { int op,l,r;cin>>op>>l>>r; if(op == 1) { int k;cin>>k; modify(1, l, r, k); } else { cout<<query(1,l,r)<<endl; } } } void main_init() {} signed main(){ AC();clapping();TLE; cout<<fixed<<setprecision(12); main_init(); // while(cin>>n,n) // while(cin>>n>>m,n,m) // int t;cin>>t;while(t -- ) solve(); // {solve(); } return 0; } /*样例区 */ //------------------------------------------------------------