hihoCoder#1080 (线段树)

题目大意:线段树的区间更改与查询,但是涉及到两种区间修改方式,一是给区间中的数全部加上一个数,二是将一个区间全部置为同一个数,然后询问整个区间和。

题目分析:处理好set操作和add操作的先后顺序就OK了。

代码如下:

# include<iostream>
# include<cstdio>
# include<cstring>
# include<algorithm>
using namespace std;

const int N=100001;

int n,m;
int tr[N*4+5];
int lazy_set[N*4+5];
int lazy_add[N*4+5];

void pushDown(int rt,int l,int r)
{
	int mid=l+(r-l)/2;
	if(lazy_set[rt]!=0){
		lazy_set[rt<<1]=lazy_set[rt<<1|1]=lazy_set[rt];
		lazy_add[rt<<1]=lazy_add[rt<<1|1]=0;
		tr[rt<<1]=lazy_set[rt]*(mid-l+1);
		tr[rt<<1|1]=lazy_set[rt]*(r-mid);
		lazy_set[rt]=0;
	}
	if(lazy_add[rt]!=0){
		lazy_add[rt<<1]+=lazy_add[rt];
		lazy_add[rt<<1|1]+=lazy_add[rt];
		tr[rt<<1]+=lazy_add[rt]*(mid-l+1);
		tr[rt<<1|1]+=lazy_add[rt]*(r-mid);
		lazy_add[rt]=0;
	}
}

void makeTree(int rt,int l,int r)
{
	if(l==r){
		scanf("%d",&tr[rt]);
	}else{
		int mid=l+(r-l)/2;
		makeTree(rt<<1,l,mid);
		makeTree(rt<<1|1,mid+1,r);
		tr[rt]=tr[rt<<1]+tr[rt<<1|1];
	}
}

void update(int rt,int l,int r,int L,int R,int x,int flag)
{
	if(L<=l&&r<=R){
		if(flag){
			lazy_set[rt]=x;
			lazy_add[rt]=0;
			tr[rt]=x*(r-l+1);
		}else{
			lazy_add[rt]+=x;
			tr[rt]+=x*(r-l+1);
		}
	}else{
		pushDown(rt,l,r);
		int mid=l+(r-l)/2;
		if(L<=mid)
			update(rt<<1,l,mid,L,R,x,flag);
		if(R>mid)
			update(rt<<1|1,mid+1,r,L,R,x,flag);
		tr[rt]=tr[rt<<1]+tr[rt<<1|1];
	}
}

int main()
{
	while(~scanf("%d%d",&n,&m))
	{
		memset(lazy_set,0,sizeof(lazy_set));
		memset(lazy_add,0,sizeof(lazy_add));
		makeTree(1,0,n);
		int flag,l,r,v;
		while(m--)
		{
			scanf("%d%d%d%d",&flag,&l,&r,&v);
			update(1,0,n,l,r,v,flag);
			printf("%d\n",tr[1]);
		}
	}
	return 0;
}

  

时间: 2024-10-24 09:17:39

hihoCoder#1080 (线段树)的相关文章

hihocoder 1080 线段树(区间更新)

题目链接:http://hihocoder.com/problemset/problem/1080 , 两种操作的线段树(区间更新). 这道题前一段时间一直卡着我,当时也是基础不扎实做不出来,今天又想了想其实还是比较简单的,也只能怪自己太弱了. 这道题坑就坑在是有两个操作:set和add,所以lazy标记数组就需要两个,但是有一点要考虑的是一个区间上set与add的先后关系——如果对于一个区间set和add标记同时存在,那么应该如果处理:一种情况set在add之前,那么就按照正常顺序来就可以了:

[Codevs] 1080 线段树练习

1080 线段树练习 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题目描述 Description 一行N个方格,开始每个格子里都有一个整数.现在动态地提出一些问题和修改:提问的形式是求某一个特定的子区间[a,b]中所有元素的和:修改的规则是指定某一个格子x,加上或者减去一个特定的值A.现在要求你能对每个提问作出正确的回答.1≤N<100000,,提问和修改的总数m<10000条. 输入描述 Input Description 输入文件第一行为一个整

codevs 1080 线段树练习--用树状数组做的

1080 线段树练习 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题目描述 Description 一行N个方格,开始每个格子里都有一个整数.现在动态地提出一些问题和修改:提问的形式是求某一个特定的子区间[a,b]中所有元素的和:修改的规则是指定某一个格子x,加上或者减去一个特定的值A.现在要求你能对每个提问作出正确的回答.1≤N<100000,,提问和修改的总数m<10000条. 输入描述 Input Description 输入文件第一行为一个整

wikioi 1080 线段树练习 树状数组

1080 线段树练习 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题目描述 Description 一行N个方格,开始每个格子里都有一个整数.现在动态地提出一些问题和修改:提问的形式是求某一个特定的子区间[a,b]中所有元素的和:修改的规则是指定某一个格子x,加上或者减去一个特定的值A.现在要求你能对每个提问作出正确的回答.1≤N<100000,,提问和修改的总数m<10000条. 输入描述 Input Description 输入文件第一行为一个整

1080 线段树练习 (codevs)

http://codevs.cn/problem/1080/ 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题目描述 Description 一行N个方格,开始每个格子里都有一个整数.现在动态地提出一些问题和修改:提问的形式是求某一个特定的子区间[a,b]中所有元素的和:修改的规则是指定某一个格子x,加上或者减去一个特定的值A.现在要求你能对每个提问作出正确的回答.1≤N<100000,,提问和修改的总数m<10000条. 输入描述 Input Des

hihoCoder #1078 : 线段树的区间修改(线段树区间更新板子题)

#1078 : 线段树的区间修改 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 对于小Ho表现出的对线段树的理解,小Hi表示挺满意的,但是满意就够了么?于是小Hi将问题改了改,又出给了小Ho: 假设货架上从左到右摆放了N种商品,并且依次标号为1到N,其中标号为i的商品的价格为Pi.小Hi的每次操作分为两种可能,第一种是修改价格——小Hi给出一段区间[L, R]和一个新的价格NewP,所有标号在这段区间中的商品的价格都变成NewP.第二种操作是询问——小Hi给出一段

hihoCoder#1079(线段树+坐标离散化)

时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 小Hi和小Ho在回国之后,重新过起了朝7晚5的学生生活,当然了,他们还是在一直学习着各种算法~ 这天小Hi和小Ho所在的学校举办社团文化节,各大社团都在宣传栏上贴起了海报,但是贴来贴去,有些海报就会被其他社团的海报所遮挡住.看到这个场景,小Hi便产生了这样的一个疑问——最后到底能有几张海报还能被看见呢? 于是小Ho肩负起了解决这个问题的责任:因为宣传栏和海报的高度都是一样的,所以宣传栏可以被视作长度为L的一段区间,且有

Codevs 1080 线段树联系

题目描述 Description 一行N个方格,开始每个格子里都有一个整数.现在动态地提出一些问题和修改:提问的形式是求某一个特定的子区间[a,b]中所有元素的和:修改的规则是指定某一个格子x,加上或者减去一个特定的值A.现在要求你能对每个提问作出正确的回答.1≤N<100000,,提问和修改的总数m<10000条. 输入描述 Input Description 输入文件第一行为一个整数N,接下来是n行n个整数,表示格子中原来的整数.接下一个正整数m,再接下来有m行,表示m个询问,第一个整数表

hihocoder 1077线段树

http://hihocoder.com/problemset/problem/1077 #include <bits/stdc++.h> using namespace std; #define ll long long #define co(x) cout << (x) << endl #define ci(x) cin >> (x) #define sd(x) scanf("%d",&x) #define sf(x) sca

hihoCoder #1078 : 线段树的区间修改

思路: 1 #include <bits/stdc++.h> 2 using namespace std; 3 const int N=100010; 4 int n, q, op, l, r, flag, sma; 5 int w[N]; 6 int ans[N]; 7 8 void cal(int t)//从t开始计算,ans[i]表示1~i的和 9 { 10 for(int i=t; i<=n; i++) 11 ans[i]=ans[i-1]+w[i]; 12 } 13 14 in