G - Greg and Array CodeForces - 296C 差分+线段树

题目大意:输入n,m,k。n个数,m个区间更新标记为1~m。n次操作,每次操作有两个数x,y表示执行第x~y个区间更新。

题解:通过差分来表示某个区间更新操作执行的次数。然后用线段树来更新区间。

#include<bits/stdc++.h>
using namespace std;
const int N=1E5+7;
typedef long long ll;
ll arr[N];
ll tt[N],cnt[N];
struct stu{
    ll value,add;
}tree[N+N+N];
ll l1[N],r1[N],v[N];
void bt(ll root,ll start,ll end){
    tree[root].add=0;
    if(start==end) {
        tree[root].value=arr[end];
        return ;
    }
    ll mid=(start+end)/2;
    bt(root*2,start,mid);
    bt(root*2+1,mid+1,end);
    tree[root].value=tree[root*2].value+tree[root*2+1].value;
}
void pushdown(ll root,ll start,ll end){
    ll mid=(start+end)/2;
    tree[root*2].value+=(mid-start+1)*tree[root].add;
    tree[root*2+1].value+=(end-mid)*tree[root].add;
    tree[root*2].add+=tree[root].add;
    tree[root*2+1].add+=tree[root].add;
    tree[root].add=0;
}
void  update(ll root,ll start,ll end,ll l,ll r,ll k){
    if(r<start||l>end) return ;
    if(start>=l&&end<=r){
        tree[root].value+=k*(end-start+1);
        tree[root].add+=k;
        return ;
    }
    pushdown(root,start,end);
    ll mid=(start+end)/2;
    update(root*2,start,mid,l,r,k);
    update(root*2+1,mid+1,end,l,r,k);
    tree[root].value=tree[root*2].value+tree[root*2+1].value;
    return ;
}

ll query(ll root,ll start,ll end,ll i){
    if(start==end) {
        if(end==i) return tree[root].value;
    }
    if(start>i||i>end) return 0;
    pushdown(root,start,end);
    ll mid=(start+end)/2;
    return query(root*2,start,mid,i)+query(root*2+1,mid+1,end,i);
}

int main()
{
    ios::sync_with_stdio(0);
    ll n,m,q;
    cin>>n>>m>>q;
    for(ll i=1;i<=n;i++) cin>>arr[i];
    for(ll i=1;i<=m;i++) cin>>l1[i]>>r1[i]>>v[i];
    bt(1,1,n);
//    for(ll i=1;i<=3*n;i++) cout<<tree[i].value<<endl;
    for(ll i=1;i<=q;i++){
        ll x,y;
        cin>>x>>y;
        tt[x]++;
        tt[y+1]--;
    }
    ll tmp=0;
    for(ll i=1;i<=m;i++){
        tmp+=tt[i];
        cnt[i]=tmp;
    }
    for(ll i=1;i<=m;i++){
        update(1,1,n,l1[i],r1[i],cnt[i]*v[i]);
    }
    for(ll i=1;i<=n;i++) cout<<query(1,1,n,i)<<" ";
    return 0;
}

原文地址:https://www.cnblogs.com/Accepting/p/12255263.html

时间: 2024-10-12 22:15:22

G - Greg and Array CodeForces - 296C 差分+线段树的相关文章

CodeForces 46DParking Lot线段树

#include <cstdio> #include <cstring> #include <algorithm> #include <climits> #include <string> #include <iostream> #include <map> #include <cstdlib> #include <list> #include <set> #include <qu

Codeforces 19D Points 线段树+set

题目链接:点击打开链接 线段树维护y值大于val的最小x值 #include <cstdio> #include <cstring> #include <algorithm> #include <vector> #include <iostream> #include <map> #include <set> #include <math.h> using namespace std; #define inf

Codeforces 444C(线段树)

区间颜色不一致就更新到底,否则lazy标记 #include<cstdio> #include<cstring> #include<cmath> #include<queue> using namespace std; #define lc l,m,index<<1 #define rc m+1,r,index<<1|1 #define N 100005 #define ll __int64 struct node { bool sa

Codeforces Round #510 (Div. 2) D. Petya and Array (权值线段树)

题目地址:http://codeforces.com/contest/1042/problem/D 题意:给你n个数,问有多少个区间的和的值小于t 分析:区间和问题,常常用到前缀和来进行预处理,所以先预处理出前缀和数组sum sum[i]代表前i个数的和,那么sum[i]的贡献就是,  当i<k<=n时,存在多少个k,使sum[k]<t+sum[i] 也就是求在[i+1,n]中,小于t+sum[i]的数有多少. 所以我们可以类比于询问一个数是区间第几大的方法,使用权值线段树来解决,这里因

APIO 2012 守卫 | 差分 / 线段树 + 贪心

题目:luogu 3634 首先把为 0 的区间删去,重新标号,可以差分也可以线段树. 把包含其他线段的线段删去,原因 1 是它没有用,原因 2 下面再说.然后,贪心选取最少的点来满足所有线段,即选取还没有点在上面的线段的右端点.如下图中选取的红色方格. 倘若不删去包含其他线段的线段,如上图中的蓝色虚线,我们在贪心选取点的时候,就会先扫到蓝线的左端点而后扫到第二条红线,按照规则,我们会选择蓝线的右端点 6 号点,接下来扫到第二条红线时,由于它上面并没有点被选取,所以又会选取它的右端点 5 号点,

[树上差分][线段树合并]JZOJ 3397 雨天的尾巴

Description 深绘里一直很讨厌雨天. 灼热的天气穿透了前半个夏天,后来一场大雨和随之而来的洪水,浇灭了一切. 虽然深绘里家乡的小村落对洪水有着顽固的抵抗力,但也倒了几座老房子,几棵老树被连 根拔起,以及田地里的粮食被弄得一片狼藉. 无奈的深绘里和村民们只好等待救济粮来维生. 不过救济粮的发放方式很特别. 首先村落里的一共有n 座房屋,并形成一个树状结构.然后救济粮分m 次发放,每次选择 两个房屋(x,y),然后对于x 到y 的路径上(含x 和y) 每座房子里发放一袋z 类型的救济粮.

LightOJ Array Queries 1082【线段树求区间最值】

1082 - Array Queries PDF (English) Statistics Forum Time Limit: 3 second(s) Memory Limit: 64 MB Given an array with N elements, indexed from 1 to N. Now you will be given some queries in the form I J, your task is to find the minimum value from index

Manthan, Codefest 16(G. Yash And Trees(dfs序+线段树))

题目链接:点击打开链接 题意:给你一棵树, 根结点为1, q组操作, 每组操作有两种, 一种是对一个结点的所有子树结点的值全部+1, 另一种是查询一个结点的子树结点上值%m的余数为素数的个数. 思路:对于第一个操作, 我们可以想到用dfs序给树重新标号, 使得一个结点的子树结点为相邻的一条线段, 这样,就可以很容易的用线段树进行处理了.  对于第二个操作, 为了维护一个区间内的值, 我们可以用bitset作为结点信息.  我们可以开一个m位的bitset, 对于每个位, 1表示这个数在此区间中,

[LuoguP1438]无聊的数列(差分+线段树/树状数组)

\(Link\) \(\mathcal{Description}\) 给你一个数列,要求支持单点查询\(and\)区间加等差数列. \(\mathcal{Solution}\) 哈哈哈哈这个题十分的有意思,至于为什么有意思等会儿再说~ 其实我们观察这两个操作,单点查询--就是那个\(naive\)的单点查询,那么区间加等差数列呢?我们可以思考一下等差数列的性质--存在公差.不妨考虑差分 \(emmm\)发现我好像还没有在博客园里提过差分--那么就整一整吧正好我好久没捯饬这玩意儿了\(qwq\)