http://codeforces.com/contest/296/problem/C
线段树的成段更新模板提
对于k的情况可以先行处理,具体看代码
因为很久以前学线段树只会了单点更新,但是知道有这样的题,于是果然在notonlysuccess大神的博客上找到了模板,改了一下accept了。
View Code
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; #define lson l , m , rt << 1 #define rson m + 1 , r , rt << 1 | 1 #define LL long long const int maxn = 111111; LL add[maxn<<3]; LL sum[maxn<<3]; void PushUp(int rt) { sum[rt] = sum[rt<<1] + sum[rt<<1|1]; } void PushDown(int rt,int m) { if (add[rt]) { add[rt<<1] += add[rt]; add[rt<<1|1] += add[rt]; sum[rt<<1] += add[rt] * (m - (m /2)); sum[rt<<1|1] += add[rt] * (m /2); add[rt] = 0; } } void build(int l,int r,int rt) { add[rt] = 0; if (l == r) { cin >> sum[rt]; return ; } int m = (l + r) >> 1; build(lson); build(rson); PushUp(rt); } void update(int L,int R,LL c,int l,int r,int rt) { if (L <= l && r <= R) { add[rt] += c; sum[rt] += (LL)c * (r - l + 1); return ; } PushDown(rt , r - l + 1); int m = (l + r) >> 1; if (L <= m) update(L , R , c , lson); if (m < R) update(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); int m = (l + r) >> 1; LL ret = 0; if (L <= m) ret += query(L , R , lson); if (m < R) ret += query(L , R , rson); return ret; } int n , m , k; LL L[maxn] , R[maxn] , D[maxn] , C[maxn]; LL ANS[maxn]; int main() { cin >> n >> m >> k; //for(int i=1;i<=n;i++) cin >> ANS[i]; build(1 , n , 1); for(int i=1;i<=m;i++){ cin >> L[i] >> R[i] >> D[i]; //update(li,ri,di,1,n,1); } for(int i=0;i<k;i++) { int li , ri; cin >> li >> ri; C[li] += 1; C[ri+1] -= 1; } for(int i=2;i<=m;i++) C[i] += C[i-1]; for(int i=1;i<=m;i++) { update(L[i],R[i],D[i]*C[i],1,n,1); } cout <<query(1,1,1,n,1); for(int i=2;i<=n;i++) cout<<" "<<query(i,i,1,n,1); return 0; }