• 题解【SP8002】HORRIBLE


    题面

    题解

    这是一道线段树的模板题。

    题目需要我们维护一个支持区间修改、区间查询的一个数据结构,很容易想到线段树。

    然后发现和洛谷上线段树的模板1是同一道题。

    由于本题中每个数的初始值都为(0),因此我们就不需要建树,直接开始把树上每个结点的值都初始化成(0)即可。

    修改时寻找指定区间,维护一下(lazy tag)并更新节点的值即可。

    查询时和修改同理,只是把查找更新的区间变成了加上区间的和。

    注意:

    1. 数据有(T)组,因此每组数据开头都需要清空数组;
    2. (lazy tag)标记下传时要注意最后清空当前节点的(lazy tag)
    3. 需要开(long long)

    代码

    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    #include <cctype>
    #define int long long
    #define itn int
    #define gI gi
    
    using namespace std;
    
    inline int gi()
    {
    	int f = 1, x = 0; char c = getchar();
    	while (c < '0' || c > '9') { if (c == '-') f = -1; c = getchar();}
    	while (c >= '0' && c <= '9') { x = x * 10 + c - '0'; c = getchar();}
    	return f * x;
    }
    
    int n, ans[100005 << 2], tag[100005 << 2];
    
    inline int ls(int x) {return x << 1;}//左儿子
    inline int rs(int x) {return x << 1 | 1;}//右儿子
    
    inline void push_up(int x)//上传标记
    {
    	ans[x] = ans[ls(x)] + ans[rs(x)];//求和
    }
    
    inline void pushdown(int p, int l, int r)//下传标记
    {
    	if (tag[p])//如果还有标记
    	{
    		ans[ls(p)] = ans[ls(p)] + tag[p] * l;
    		ans[rs(p)] = ans[rs(p)] + tag[p] * r;//加上和
    		tag[ls(p)] = tag[ls(p)] + tag[p];
    		tag[rs(p)] = tag[rs(p)] + tag[p];//加上标记
    		tag[p] = 0;//清零标记
    	}
    }
    
    void upd(int nl, int nr, int l, int r, int p, int k)//更新操作
    {
    	if (nl <= l && nr >= r)//当前区间包含于要更新的区间
    	{
    		ans[p] = ans[p] + (r - l + 1) * k, tag[p] = tag[p] + k;//加上和并记录lazy标记
    		return;
    	}
    	int mid = (l + r) >> 1;
    	pushdown(p, mid - l + 1, r - mid);//下传lazy标记
    	if (nl <= mid) upd(nl, nr, l, mid, ls(p), k);//更新左区间
    	if (nr > mid) upd(nl, nr, mid + 1, r, rs(p), k);//更新右区间
    	push_up(p);//上传节点
    }
    
    int getans(int ql, int qr, int l, int r, int p)//求和操作,与更新同理
    {
    	int sum = 0;
    	if (ql <= l && qr >= r) return ans[p];
    	int mid = (l + r) >> 1;
    	pushdown(p, mid - l + 1, r - mid);
    	if (ql <= mid) sum = sum + getans(ql, qr, l, mid, ls(p));
    	if (qr > mid) sum = sum + getans(ql, qr, mid + 1, r, rs(p));
    	return sum;
    }
    
    signed main()
    {
    	int T = gi();
    	while (T--)//多组数据
    	{
    	memset(tag, 0, sizeof(tag));
    	memset(ans, 0, sizeof(ans));//多组数据记得清空数组
    	int n = gi(), m = gi();
    	for (int i = 1; i <= m; i++)
    	{
    		int fl = gi();
    		if(fl == 0)//修改操作
    		{
    			int x = gi(), y = gi(), k = gi();
    			upd(x, y, 1, n, 1, k);
    		}
    		else//求和操作
    		{
    			int x = gi(), y = gi();
    			printf("%lld
    ", getans(x, y, 1, n, 1));
    		}
    	}
    	}
    	return 0;//结束
    }
    
  • 相关阅读:
    Window Phone 8手电筒
    Wp检查手机网络状态
    Wp 导航到手机定位设置页面
    Wp8 读取手机信息
    移动端丨-webkit-overflow-scrolling:touch属性导致页面卡住
    小程序丨canvas内容自适应不同尺寸屏幕
    钉钉自带浏览器版本过低,导致Object.assign不兼容...
    HTTP中GET与POST的区别
    git丨Push rejected: Push to origin/master was rejected
    小程序丨嵌套循环
  • 原文地址:https://www.cnblogs.com/xsl19/p/11370423.html
Copyright © 2020-2023  润新知