CodeForces296C【线段树】

思路:
线段树模拟。
先求操作数,然后操作数 * 增值 再一个线段树就好了

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;

const int N = 1e5 + 10;

struct Seg{
    LL Left;
    LL Right;
    LL sum;
    LL flag;
}node1[N<<2], node2[N<<2];
LL a[N];

void PushDown(int num, Seg node[]){
    if(node[num].flag){
        node[num<<1].flag += node[num].flag;
        node[num<<1].sum += node[num].flag * (node[num<<1].Right - node[num<<1].Left + 1);
        node[num<<1|1].flag += node[num].flag;
        node[num<<1|1].sum += node[num].flag * (node[num<<1|1].Right - node[num<<1|1].Left + 1);
        node[num].flag = 0;
    }
}

void Build(int num, int Left, int Right, Seg node[]){
    node[num].Left = Left;
    node[num].Right = Right;
    node[num].flag = 0;
    if(Left == Right){
        node[num].sum = a[Left];
        return;
    }
    int mid = (Left + Right) >> 1;
    Build(num<<1, Left, mid, node);
    Build(num<<1|1,mid+1,Right,node);
    node[num].sum = node[num<<1].sum + node[num<<1|1].sum;
}

void Update(int num, int s, int t, LL val, Seg node[]){
    if(node[num].Left >= s && node[num].Right <= t){
        node[num].flag += val;
        node[num].sum += val * (node[num].Right - node[num].Left + 1LL);
        return;
    }
    PushDown(num, node);
    int mid = (node[num].Left + node[num].Right) >> 1;
    if(mid >= t) Update(num<<1, s, t, val, node);
    else if(mid < s) Update(num<<1|1, s, t, val, node);
    else{
        Update(num<<1, s, mid, val, node);
        Update(num<<1|1, mid + 1, t, val, node);
    }
    node[num].sum = node[num<<1].sum + node[num<<1|1].sum;
}

LL Query(int num, int v, Seg node[]){
    if(node[num].Left == node[num].Right){
        if(node[num].Left == v)
            return node[num].sum;
        return 0;
    }
    PushDown(num, node);
    int mid = (node[num].Left + node[num].Right) >> 1LL;
    if(mid >= v)  return Query(num<<1, v, node);
    return Query(num<<1|1, v, node);
}
int n, m, k;
struct asd{
    int Left;
    int Right;
    LL val;
}q[N];
int u, v;

int main(){
    scanf("%d%d%d",&n, &m, &k);
    for(int i=1;i<=n;i++) scanf("%I64d", &a[i]);
    Build(1, 1, n, node1);
    for(int i=1;i<=m;i++)
        scanf("%d%d%I64d",&q[i].Left, &q[i].Right, &q[i].val);

    for(int i=1;i<=m;i++) a[i] = 0;
    Build(1, 1, m, node2);

    for(int i=1;i<=k;i++){
        scanf("%d%d",&u,&v);
        Update(1, u, v, 1LL, node2);
    }

    for(int i=1;i<=m;i++){
        LL op = Query(1,i,node2);
        Update(1,q[i].Left,q[i].Right, q[i].val*op, node1);
    }
    for(int i=1;i<=n;i++)
        printf("%I64d ",Query(1,i,node1));
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值