zoukankan      html  css  js  c++  java
  • 洛谷OJ U552 守墓人 线段树模板题

    题目描述 Description

    在一个荒凉的墓地上
    有一个令人尊敬的守墓人, 他看守的墓地从来
    没有被盗过, 所以人们很放心的把自己的先人的墓
    安顿在他那
    守墓人能看好这片墓地是必然而不是偶然.....
    因为....守墓人懂风水 0.0
    他把墓地分为主要墓碑和次要墓碑, 主要墓碑
    只能有 1 个, 守墓人把他记为 1 号, 而次要墓碑有
    n-1 个,守墓人将之编号为 2,3...n,所以构成了一个有 n 个墓碑的墓地。
    而每个墓碑有一个初始的风水值,这些风水值决定了墓地的风水的好坏,所以守墓人
    需要经常来查询这些墓碑。
    善于运用风水的守墓人,通过一次次逆天改命,使得自己拥有了无限寿命,没人知道
    他活了多久。
    这天,你幸运的拜访到了他,他要求你和他共同见证接下来几年他的战果,但不过他
    每次统计风水值之和都需要你来帮他计算,算错了他会要你命 QAQ
    风水也不是不可变,除非遭遇特殊情况,已知在接下来的 2147483647 年里,会有 n 次
    灾难,守墓人会有几个操作:
    1.将[l,r]这个区间所有的墓碑的风水值增加 k。
    2.将主墓碑的风水值增加 k
    3.将主墓碑的风水值减少 k
    4.统计[l,r]这个区间所有的墓碑的风水值之和
    5.求主墓碑的风水值
    上面也说了,很多人会把先人的墓安居在这里,而且守墓人活了很多世纪→_→,墓碑
    的数量会多的你不敢相信= =
    守墓人和善的邀请你帮他完成这些操作,要不然哪天你的旅馆爆炸了,天上下刀子.....
    为了活命,还是帮他吧

    输入输出格式 Input/output

    输入格式:
    第一行,两个正整数 n,f 表示共有 n 块墓碑,并且在接下来的
    2147483647 年里,会有 f 次世界末日
    第二行,n 个正整数,表示第 i 块墓碑的风水值
    接下来 f 行,每行都会有一个针对世界末日的解决方案,如题所述,标记同题

    输出格式:

    输出会有若干行,对 4 和 5 的提问做出回答

    输入输出样例 Sample input/output

    样例测试点#1

    输入样例:

    5 6
    0 0 0 0 0
    1 1 5 1
    1 1 3 3
    2 3
    3 1
    4 1
    5

    输出样例:

    16
    7

    说明 description

    20%的数据满足:1≤n≤100
    50%的数据满足:1≤n≤6000
    100%的数据满足:1≤n,f≤2*10^5

    #include <iostream>
    #include <cstdio>
    using namespace std;
    
    #define ls id<<1
    #define rs (id<<1)+1
    #define lson l,mid,ls
    #define rson mid+1,r,rs
    
    const int maxn=200001;
    
    struct segment_tree{
    	int l,r;
    	long long tag,num;
    	segment_tree(){tag=num=l=r=0;}
    }t[maxn*4];
    
    int n,f;
    int num[maxn];
    
    void push_up(int id){
    	t[id].num=t[ls].num+t[rs].num;
    }
    
    void push_down(int id){
    	if(t[id].tag){
    		t[ls].tag+=t[id].tag;
    		t[rs].tag+=t[id].tag;
    		t[ls].num+=t[id].tag*(t[ls].r-t[ls].l+1);
    		t[rs].num+=t[id].tag*(t[rs].r-t[rs].l+1);
    		t[id].tag=0;
    	}
    }
    
    void build(int l,int r,int id){
    	t[id].l=l;t[id].r=r;
    	if(l==r){
    		t[id].num=num[l];
    		t[id].tag=0;
    		return;
    	}
    	int mid=(l+r)>>1;
    	build(lson);
    	build(rson);
    	push_up(id);
    }
    
    long long query(int L,int R,int id){
    	if(L<=t[id].l && t[id].r<=R)return t[id].num;
    	push_down(id);
    	long long res=0;
    	int mid=(t[id].l+t[id].r)>>1;
    	if(mid<L)
    	   res=query(L,R,rs); 
    	else
    	  if(mid>=R)
    	    res=query(L,R,ls);
    	  else 
    	  	res=query(L,mid,ls)+query(mid+1,R,rs);
    	return res;
    }
    
    void update(int L,int R,int id,int c){
    	if(L<=t[id].l && t[id].r<=R){
    		t[id].num+=(t[id].r-t[id].l+1)*c;
    		t[id].tag+=c;
    		return;
    	}
    	push_down(id);
    	if(R>=t[rs].l)update(L,R,rs,c);
    	if(L<=t[ls].r)update(L,R,ls,c);
    	push_up(id);
    }
    
    int main(){
    	scanf("%d%d",&n,&f);
    	int i,x,l,r,k;
    	for(i=1;i<=n;i++)
    	  scanf("%d",&num[i]);
    	build(1,n,1);
    	for(i=1;i<=f;i++){
    		scanf("%d",&x);
    		if(x==1){
    		    scanf("%d%d%d",&l,&r,&k);
    			update(l,r,1,k);
    		}
    		if(x==2){
    		    scanf("%d",&k);
    			update(1,1,1,k);
    		}
    		if(x==3){
    		    scanf("%d",&k);
    		    update(1,1,1,-k);
    		}
    		if(x==4){
    		    scanf("%d%d",&l,&r);
    			printf("%lld
    ",query(l,r,1));
    		}
    		if(x==5)printf("%lld
    ",query(1,1,1));
    	}
    	return 0;
    }
  • 相关阅读:
    用 tableExcel导出EXCEL数据
    个人作业——软件评测
    结对第二次作业——某次疫情统计可视化的实现
    软工实践寒假作业(1/2)
    java注解和反射
    共享密钥
    鲁棒性验证-第五小组
    维数约减报告--第五小组
    网络1911、1912 D&S第1次作业--线性表批改总结
    网络1911、1912 C语言第4次作业--函数批改总结
  • 原文地址:https://www.cnblogs.com/qscqesze/p/4322160.html
Copyright © 2011-2022 走看看