• D


    - 题目大意

        有两种命令,Q是查询一个区间的和,C是一个区间同时增加一个数。

    - 解题思路

        主要是线段树的点的更新和存储问题。每个一个数都更新到叶子节点不是明智的做法,很消耗时间。故每个节点加一个特殊量来记录增量的累加。

    - 代码

    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<algorithm>
    #include<cstring>
    #include<stack>
    using namespace std;
    const int maxn = 100001;
    int num[maxn];
    struct node
    {
    	int l, r;
    	long long a,s;
    }t[4 * maxn];
    long long ans;
    void build(int l, int r, int k)
    {
    	int mid;
    	t[k].l = l;
    	t[k].r = r;
    	t[k].a=0;
    	if (l == r)
    	    return;
        mid = (l + r) / 2;
        build(l, mid, 2 * k);
        build(mid + 1, r, 2 * k + 1);
        t[k].s=t[k*2].s+t[k*2+1].s;
    
    }
    
    void add(int l, int r, int x,int i)
    {
    	int mid;
    	if(t[i].l>r||t[i].r<l)
            return;
    	mid = (t[i].r + t[i].l) / 2;
    	if (t[i].l>=l&&t[i].r<=r)
        {
            t[i].s+=(t[i].r-t[i].l+1)*x;
            t[i].a+=x;
            return;
        }
        if(t[i].a)
        {
            t[i*2].s+=(t[i*2].r-t[i*2].l+1)*t[i].a;
            t[i*2].a+=t[i].a;
            t[i*2+1].s+=(t[i*2+1].r-t[i*2+1].l+1)*t[i].a;
            t[i*2+1].a+=t[i].a;
            t[i].a=0;
        }
        add(l,r,x,i*2);
        add(l,r,x,i*2+1);
    	t[i].s=t[i*2].s+t[i*2+1].s;
    }
    
    void findd(int l,int r, int i)
    {
    	int mid;
    	if(t[i].l>r||t[i].r<l)
            return;
        if(t[i].l>=l&&t[i].r<=r)
        {
            ans+=t[i].s;
            return;
        }
        if(t[i].a)
        {
            t[i*2].s+=(t[i*2].r-t[i*2].l+1)*t[i].a;
            t[i*2].a+=t[i].a;
            t[i*2+1].s+=(t[i*2+1].r-t[i*2+1].l+1)*t[i].a;
            t[i*2+1].a+=t[i].a;
            t[i].a=0;
        }
        findd(l,r,i*2);
        findd(l,r,i*2+1);
    	t[i].s=t[i*2].s+t[i*2+1].s;
    }
    
    int main()
    {
    	int n, m, a,b,c;
    	char str[2];
    	scanf("%d%d", &n, &m);
    	for(int i=1;i<=n;i++)
            scanf("%d",&num[i]);
    	build(1, n, 1);
        for(int i=1;i<=n;i++)
            add(i,i,num[i],1);
        while(m--)
        {
            scanf("%s",&str);
            if(str[0]=='C')
            {
                scanf("%d%d%d",&a,&b,&c);
                add(a,b,c,1);
            }
            if(str[0]=='Q')
            {
                ans=0;
                scanf("%d%d",&a,&b);
                findd(a,b,1);
                printf("%lld
    ",ans);
            }
        }
    	return 0;
    }
    

      

  • 相关阅读:
    iOS崩溃报告获取一
    GCDTimer
    Runtime
    Socket
    冒泡排序笔记
    学习java虚拟机笔记
    ftp发送文件包括中文名
    java email
    批量数据插入高效 转发
    读取本地硬盘文件,快速扫描插入 数据库
  • 原文地址:https://www.cnblogs.com/alpacadh/p/8521622.html
Copyright © 2020-2023  润新知