小L正在组织acm暑假集训,但众所周知,暑假集训的萌新中有OI神犇,也有暑假才开始学算法的萌新,如果统一集训的难度,无法很好地让萌新们得到训练,所以小L想了一个办法,根据每次测试的情况,改变萌新们的集训难度。现在将萌新们编号为1到n,最初萌新们的集训难度为v0,测试后有两种操作,第一种是某一区间的萌新的集训难度同时提高,另一种是将某一段区间的萌新的集训难度变为同一个数,同时,Wells希望在某次调整难度之后,知道某一段区间的萌新的集训难度之和,由于小L比较鶸,他并不知道如何快速解决这个问题,你能帮帮他嘛?
Input
第一行三个数n,m,v0 表示有n名萌新和m次调整,初始时全部萌新的集训难度都为v0
第2~m+1行 每行三个数或四个数
0 x y v 表示把 [x,y]区间内的萌新的集训难度都增加v
1 x y v 表示把 [x,y]区间内的萌新的集训难度都变为v
2 x y表示询问[x,y]区间内萌新的集训难度之和
0<n,m<=10^5, |v|<=10^5
Output
每个询问一行,输出答案
Sample Input
3 5 0 0 1 3 1 1 2 3 2 2 1 1 2 2 2 2 2 3
Sample Output
1 2 4
Hint
题解:线段树基本操作,区间加上一个数,区间变为一个数,区间和;
1 #include<cstdio> 2 #include<algorithm> 3 #define N 100001 4 using namespace std; 5 int n,m,x,y; 6 long long z,val,ans; 7 struct node 8 { 9 int l,r,siz; 10 long long set,add,sum; 11 bool v; 12 } tree[N<<2]; 13 14 void build(int k,int l,int r) 15 { 16 tree[k].l=l; tree[k].r=r; tree[k].siz=r-l+1; 17 if(l==r) 18 { 19 tree[k].sum=val; 20 return ; 21 } 22 int mid=l+r>>1; 23 build(k<<1,l,mid); 24 build(k<<1|1,mid+1,r); 25 tree[k].sum=tree[k<<1].sum+tree[k<<1|1].sum; 26 } 27 28 void pushup(int k) 29 { 30 tree[k].sum=tree[k<<1].sum+tree[k<<1|1].sum; 31 } 32 33 void pushdown_set(int k) 34 { 35 tree[k<<1].add=tree[k<<1|1].add=0; 36 tree[k<<1].set=tree[k<<1|1].set=tree[k].set; 37 tree[k<<1].v=tree[k<<1|1].v=true; 38 tree[k<<1].sum=tree[k<<1].siz*tree[k].set; 39 tree[k<<1|1].sum=tree[k<<1|1].siz*tree[k].set; 40 tree[k].v=false; tree[k].set=0; 41 } 42 43 void pushdown_add(int k) 44 { 45 tree[k<<1].sum+=tree[k<<1].siz*tree[k].add; 46 tree[k<<1|1].sum+=tree[k<<1|1].siz*tree[k].add; 47 tree[k<<1].add+=tree[k].add; 48 tree[k<<1|1].add+=tree[k].add; 49 tree[k].add=0; 50 } 51 52 void Set(int k,int l,int r,long long z)//区间修改为某个值 53 { 54 if(tree[k].l>=l&&tree[k].r<=r) 55 { 56 tree[k].set=z; tree[k].v=true; 57 tree[k].sum=z*tree[k].siz; 58 tree[k].add=0; 59 return; 60 } 61 if(tree[k].v) pushdown_set(k); 62 if(tree[k].add) pushdown_add(k); 63 int mid=tree[k].l+tree[k].r>>1; 64 if(l<=mid) Set(k<<1,l,r,z); 65 if(r>mid) Set(k<<1|1,l,r,z); 66 pushup(k); 67 } 68 69 void Add(int k,int l,int r,long long z)//区间加上某个值 70 { 71 if(tree[k].l>=l&&tree[k].r<=r) 72 { 73 tree[k].add+=z; 74 tree[k].sum+=z*tree[k].siz; 75 return; 76 } 77 if(tree[k].v) pushdown_set(k); 78 if(tree[k].add) pushdown_add(k); 79 int mid=tree[k].l+tree[k].r>>1; 80 if(l<=mid) Add(k<<1,l,r,z); 81 if(r>mid) Add(k<<1|1,l,r,z); 82 pushup(k); 83 } 84 85 void query(int k,int l,int r) 86 { 87 if(tree[k].l>=l&&tree[k].r<=r) 88 { 89 ans+=tree[k].sum; 90 return; 91 } 92 if(tree[k].v) pushdown_set(k); 93 if(tree[k].add) pushdown_add(k); 94 int mid=tree[k].l+tree[k].r>>1; 95 if(l<=mid) query(k<<1,l,r); 96 if(r>mid) query(k<<1|1,l,r); 97 } 98 int main() 99 { 100 scanf("%d%d%lld",&n,&m,&val); 101 build(1,1,n); 102 while(m--) 103 { 104 int temp; 105 scanf("%d",&temp); 106 if(temp==0) 107 { 108 scanf("%d%d%lld",&x,&y,&z); 109 Add(1,x,y,z); 110 } 111 else if(temp==1) 112 { 113 scanf("%d%d%lld",&x,&y,&z); 114 Set(1,x,y,z); 115 } 116 else 117 { 118 scanf("%d%d",&x,&y); 119 ans=0; 120 query(1,x,y); 121 printf("%lld\n",ans); 122 } 123 124 } 125 }
参考代码: