zoukankan      html  css  js  c++  java
  • 魔法树

    Description

    人类和精灵的联络被巫妖王破坏了,巫妖王决定消灭精灵族以绝后患。 拉席克:“亡灵正在攻过来!” 法里奥:“看来只有暂时抵挡了。” 作为精灵的先知,法里奥召唤出了一排树木,挡住了亡灵的进攻,可是亡灵改变战略,集中攻击一段树木,法里奥为了加强防御不 得不施魔法将这一段树加高。 
    对于亡灵的每一次进攻,法里奥需要知道进攻区间的防御力, 定义区间的防御力为这一段区间所有树的高度和。 
    法里奥还在忙着施法,所以需要你来帮他完成这个任务

    Input

    第一行,两个数 N,M,表示树的数量和操作数,数的编号为0到N−1。 
    第二行 N 个数,表示树的初始高度。 
    接下来 M 行,每行一个操作: 
    C l r h 表示法里奥施法将 l 到 r 的树加高了 ℎ 
    Q l r 表示亡灵攻击了 l 到 r,法里奥向你询问 l 到 r 之间树的高度和。

    Output

    对于每一个 Q 操作,输出一个结果。

    Sample Input

     

    10 5
    1 2 3 4 5 6 7 8 9 10
    Q 3 3
    Q 0 9
    Q 1 3
    C 2 5 3
    Q 1 3

     

    Sample Output

     

    4
    55
    9
    15

     

    Hint

    N≤1000000,M≤5000 初始高度不超过 100


    【分析】

            这道题的M其实很小,那么我们只需要记下每次操作,然后每次询问暴力扫一遍即可。

            但是我用这道题来演示一下堆式线段树(也叫完全二叉线段树)


    【代码】

    /*
        若当前这段的编号为id。
    	则在堆式线段树中,其左儿子编号为id*2,右儿子编号为id*2+1
    	(跟堆的记法一样)
    	这样可以压常数,有些时候很有用。 
    */ 
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<cmath>
    #include<ctime>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    struct node{                   
    	int L,R;
    	long long sum,lazy;
    }Tree[4000005];
    int N,M,h[1000005];;
    char t[100];
    void _in(int &x)
    {
    	char t=getchar();
    	while(t<'0'||'9'<t) t=getchar();
    	for(x=t-'0',t=getchar();'0'<=t&&t<='9';x=x*10+t-'0',t=getchar()); 
    }
    void _out(long long x,int j=1)
    {
        if(x==0)printf("0");
        for(;x;x/=10,j++) t[j]=x%10+'0';
        for(j--;j;j--)putchar(t[j]);
        putchar('
    ');
    }
    void _putdown(int id)
    {
    	Tree[(id<<1)].lazy+=Tree[id].lazy;
    	Tree[(id<<1)+1].lazy+=Tree[id].lazy;
    	Tree[(id<<1)].sum+=Tree[id].lazy*((long long)(Tree[(id<<1)].R+1-Tree[(id<<1)].L));
    	Tree[(id<<1)+1].sum+=Tree[id].lazy*((long long)(Tree[(id<<1)+1].R+1-Tree[(id<<1)+1].L));
    	Tree[id].lazy=0;
    }
    void _built(int id,int l,int r)
    {
    	Tree[id].L=l;Tree[id].R=r;
    	if(l==r)
    	{
    	    Tree[id].sum=h[l];
    	    return;
    	}
    	int mid=(l+r)>>1;
    	_built((id<<1),l,mid);
    	_built((id<<1)+1,mid+1,r);
    	Tree[id].sum=Tree[(id<<1)].sum+Tree[(id<<1)+1].sum;
    }
    void _insert(int id,int l,int r,int v)
    {
    	if(Tree[id].lazy!=0&&Tree[id].R!=Tree[id].L)
    	    _putdown(id);
    	if(l<=Tree[id].L&&Tree[id].R<=r)
    	{
    		Tree[id].lazy+=v;
    		Tree[id].sum+=((long long)(v))*((long long)(Tree[id].R+1-Tree[id].L));
    		return;
    	}
    	if(!(r<Tree[(id<<1)].L||Tree[(id<<1)].R<l)) _insert((id<<1),l,r,v);
    	if(!(r<Tree[(id<<1)+1].L||Tree[(id<<1)+1].R<l)) _insert((id<<1)+1,l,r,v);
    	Tree[id].sum=Tree[(id<<1)].sum+Tree[(id<<1)+1].sum;
    }
    long long _findans(int id,int l,int r)
    {
    	if(Tree[id].lazy!=0&&Tree[id].L!=Tree[id].R)
    	    _putdown(id);
    	if(l<=Tree[id].L&&Tree[id].R<=r)
    	    return Tree[id].sum;
    	long long temp=0;
    	if(!(r<Tree[(id<<1)].L||Tree[(id<<1)].R<l))
    	    temp+=_findans((id<<1),l,r);
    	if(!(r<Tree[(id<<1)+1].L||Tree[(id<<1)+1].R<l))
    	    temp+=_findans((id<<1)+1,l,r);
    	return temp;
    }
    void _init()
    {
    	_in(N);_in(M);
    	for(int i=1;i<=N;i++)
    	    _in(h[i]);
    	_built(1,1,N);
    }
    void _solve()
    {
    	string s;
    	int x,y,z;
    	for(int i=1;i<=M;i++)
    	{
    		cin>>s;
    		_in(x);_in(y);
    		x++;y++;
    		if(s[0]=='C')
    		{
    			_in(z);
    			_insert(1,x,y,z);
    		}
    		else
    		    _out(_findans(1,x,y));
    	}
    }
    int main()
    {
    	_init();
    	_solve();
    	return 0;
    }



  • 相关阅读:
    bstToDoublyList
    Springboot系列1_什么是Springboot
    servlet总结
    JavaFx开发桌面软件
    在Emacs中使用plantuml画UML图
    IIS7.0上传文件限制的解决方法
    开源免费的天气预报接口API以及全国所有地区代码(国家气象局提供)
    如何得到天气情况?在那个接口获取?
    Windows Update 时出现8024402C的错误
    OC中copy的使用
  • 原文地址:https://www.cnblogs.com/riskyer/p/3366064.html
Copyright © 2011-2022 走看看