CSU OJ2151 集训难度

小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 }

 

参考代码:

转载于:https://www.cnblogs.com/songorz/p/9498430.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值