hihoCoder #1078 : 线段树的区间修改
题目大意及分析:
线段树成段更新裸题。
代码如下:
# include<iostream> # include<cstdio> # include<cstring> # include<algorithm> using namespace std; const int N=100000; int n,m; int a[N+5]; int tr[N*4+5]; int lazy[N*4+5]; void pushDown(int rt,int l,int r) { if(lazy[rt]!=-1){ int mid=l+(r-l)/2; tr[rt<<1]=lazy[rt]*(mid-l+1); tr[rt<<1|1]=lazy[rt]*(r-mid); lazy[rt<<1]=lazy[rt<<1|1]=lazy[rt]; lazy[rt]=-1; } } void makeTree(int rt,int l,int r) { if(l==r){ scanf("%d",&tr[rt]); }else{ int mid=l+(r-l)/2; makeTree(rt<<1,l,mid); makeTree(rt<<1|1,mid+1,r); tr[rt]=tr[rt<<1]+tr[rt<<1|1]; } } void update(int rt,int l,int r,int L,int R,int x) { if(L<=l&&r<=R){ lazy[rt]=x; tr[rt]=x*(r-l+1); }else{ pushDown(rt,l,r); int mid=l+(r-l)/2; if(L<=mid) update(rt<<1,l,mid,L,R,x); if(R>mid) update(rt<<1|1,mid+1,r,L,R,x); tr[rt]=tr[rt<<1]+tr[rt<<1|1]; } } int query(int rt,int l,int r,int L,int R) { if(L<=l&&r<=R) return tr[rt]; pushDown(rt,l,r); int res=0; int mid=l+(r-l)/2; if(L<=mid) res+=query(rt<<1,l,mid,L,R); if(R>mid) res+=query(rt<<1|1,mid+1,r,L,R); return res; } int main() { while(~scanf("%d",&n)) { memset(tr,0,sizeof(tr)); memset(lazy,-1,sizeof(lazy)); makeTree(1,1,n); scanf("%d",&m); int flag,a,b,c; while(m--) { scanf("%d",&flag); if(flag){ scanf("%d%d%d",&a,&b,&c); update(1,1,n,a,b,c); }else{ scanf("%d%d",&a,&b); printf("%d\n",query(1,1,n,a,b)); } } } return 0; }