CSU 2151 集训难度【多标记线段树】
http://acm.csu.edu.cn/csuoj/problemset/problem?pid=2151
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
多标记线段树处理法(洛谷3373,codevs4927)
#include<cstdio> #include<string> #include<cstdlib> #include<cmath> #include<iostream> #include<cstring> #include<set> #include<queue> #include<algorithm> #include<vector> #include<map> #include<cctype> #include<stack> #include<sstream> #include<list> #include<assert.h> #include<bitset> #include<numeric> #define debug() puts("++++") #define gcd(a,b) __gcd(a,b) #define lson l,mid,rt<<1 #define rson mid+1,r,rt<<1|1 #define fi first #define se second #define pb push_back #define sqr(x) ((x)*(x)) #define ms(a,b) memset(a,b,sizeof(a)) #define sz size() #define be begin() #define pu push_up #define pd push_down #define cl clear() #define mdzz int mid=(l+r)>>1; #define lowbit(x) -x&x #define all 1,n,1 #define rep(i,x,n) for(int i=(x); i<(n); i++) #define in freopen("in.in","r",stdin) #define out freopen("out.out","w",stdout) using namespace std; typedef long long ll; typedef unsigned long long ULL; typedef pair<int,int> P; const int INF = 0x3f3f3f3f; const ll LNF = 1e18; const int maxn = 200010 + 20; const int maxm = 1e6 + 10; const double PI = acos(-1.0); const double eps = 1e-8; const int dx[] = {-1,1,0,0,1,1,-1,-1}; const int dy[] = {0,0,1,-1,1,-1,1,-1}; int dir[4][2] = {{0,1},{0,-1},{-1,0},{1,0}}; const int mon[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; const int monn[] = {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; int n,m; int x,y,op; ll a[maxn]; ll sum[maxn<<2],add[maxn<<2],cover[maxn<<2],z,v; void pushup(int rt) { sum[rt]=sum[rt<<1]+sum[rt<<1|1]; //区间查询和 } void pushdown(int rt,int m) { if(cover[rt]) { //区间覆盖 cover[rt<<1] = cover[rt<<1|1] = cover[rt]; sum[rt<<1] = cover[rt]*(m-(m>>1)); sum[rt<<1|1] = cover[rt]*(m>>1); add[rt<<1] = add[rt<<1|1] = 0; //set操作中取消add cover[rt] = 0; } if(add[rt]) { //区间求和 add[rt<<1] += add[rt]; add[rt<<1|1] += add[rt]; sum[rt<<1] += add[rt]*(m-(m>>1)); sum[rt<<1|1] += add[rt]*(m>>1); add[rt]=0; } } void build(int l,int r,int rt) { add[rt]=cover[rt]=0; if(l==r) { sum[rt]=v; return; } mdzz build(lson); build(rson); pushup(rt); } void update(int op,int L,int R,int c,int l,int r,int rt) { if(L<=l && R>=r) { if(op==0) //add { add[rt] += c; sum[rt] += (ll)c*(r-l+1); } else { cover[rt] = c; add[rt] = 0; // sum[rt] = (ll)c*(r-l+1); } return ; } pushdown(rt,r-l+1); mdzz if(L<=mid) update(op,L,R,c,lson); if(R>mid) update(op,L,R,c,rson); pushup(rt); } ll query(int L,int R,int l,int r,int rt) { if(L<=l&&R>=r) return sum[rt]; pushdown(rt,r-l+1); mdzz ll res=0; if(L<=mid) res += query(L,R,lson); if(R>mid) res += query(L,R,rson); return res; } int main() { while(~scanf("%d%d%lld",&n,&m,&v)) { build(1,n,1); while(m--) { scanf("%d",&op); if(op==2) { scanf("%d%d",&x,&y); printf("%lld\n",query(x,y,1,n,1)); } else { scanf("%d%d%lld",&x,&y,&z); update(op,x,y,z,1,n,1); } } } }