hdu 1698 线段数的区间更新 以及延迟更新

先说说区间更新和单点更新的区别 主要的区别是搜索的过程 前者需要确定一个区间 后者就是一个点就好了

贴上两者代码

void updata(int i)//单点更新
{
	int l=stu[i].l;
	int r=stu[i].r;
	int mid=(l+r)/2;//二分咯
	if(l==r&&r==x)//x为目标id 当左右节点相同的时候 就是找到这个数的时候
	{
		stu[i].maxx=y;
		return;
	}
	if(l<=x&&x<=mid) updata(i*2);//向左找
	else updata(i*2+1);//向右找
	stu[i].maxx=max(stu[i*2].maxx,stu[i*2+1].maxx);//回溯的时候 更新max的数据
}
void update(int l,int r,int count)//x,y代表要更新的区间 //区间更新
{
	if(l>=x&&r<=y)
	{
		mapp[count].sum=z*mapp[count].len;
		mapp[count].flag=z;
		return;
	}
	pushdown(count);
	int mid=(l+r)/2;
    if(x<=mid) update(l,mid,count*2);
    if(y>=mid+1) update(mid+1,r,count*2+1);
    mapp[count].sum=mapp[count*2].sum+mapp[count*2+1].sum;
}在区间更新的时候 有的时候 我们不需要更新到底部 那么 这里引进一个延迟更新的概念 在搜索包含在我们需要的区间里面时 就可以返回了

那么在下次询问的时候 怎么保证底层的数据更新呢? 这里需要一个flag标记 如果当前的flag不为0的时候 向下更新 并更改当前的flag

比如在1-10标号的区间里面 我们要更新1-5的值 上代码
#include<iostream>
#define maxn 111111
using namespace std;
int n,q,x,y,z;
struct stu
{
	int l,r,sum,flag,len;
};
stu mapp[maxn*4];
void build(int l,int r,int count)
{
	mapp[count].l=l;
	mapp[count].r=r;
	mapp[count].flag=0;
	mapp[count].len=r-l+1;
	if(l==r)
	{
		mapp[count].sum=1;
		mapp[count].flag=1;
		return;
	}
	int mid=(l+r)/2;
	build(l,mid,count*2);
    build(mid+1,r,count*2+1);
    mapp[count].sum=mapp[count*2].sum+mapp[count*2+1].sum;
}
void pushdown(int count)
{
	if(mapp[count].flag)//如果有标记 向下更新
	{
		mapp[count*2].flag=mapp[count].flag;
        mapp[count*2+1].flag=mapp[count].flag;
        mapp[count*2].sum=mapp[count].flag*mapp[count*2].len;
        mapp[count*2+1].sum=mapp[count].flag*mapp[count*2+1].len;
        mapp[count].flag=0;//更新过一次  标记得消除
	}
}//向下更新的过程
void update(int l,int r,int count)//x,y代表要更新的区间
{
	if(l>=x&&r<=y)
	if(l==r)
	{
		mapp[count].sum=z*mapp[count].len;
		mapp[count].flag=z;
		return;
	}
	pushdown(count);
	int mid=(l+r)/2;
	if(x<=mid) update(l,mid,count*2);
    if(y>=mid+1) update(mid+1,r,count*2+1);
    mapp[count].sum=mapp[count*2].sum+mapp[count*2+1].sum;
}
int main()
{
	cin.sync_with_stdio(false);
	int t;
	cin>>t;
	int casee=1;
	while(t--)
	{
		cin>>n;
		build(1,n,1);
		cin>>q;
		while(q--)
		{
			cin>>x>>y>>z;
			update(1,n,1);
		}
		cout<<"Case "<<casee++<<": The total value of the hook is ";
        cout<<mapp[1].sum<<"."<<endl;
	}
	return 0;
}
时间: 2024-07-29 09:52:56

hdu 1698 线段数的区间更新 以及延迟更新的相关文章

HDU 1698 线段树(区间染色)

Just a Hook Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 16255    Accepted Submission(s): 8089 Problem Description In the game of DotA, Pudge’s meat hook is actually the most horrible thing f

POJ 2777 &amp;&amp; ZOJ 1610 &amp;&amp;HDU 1698 --线段树--区间更新

直接将这3题 放一起了  今天在做线段树的东西 这3个都是区间更新的 查询方式互相不同 反正都可以放到一起吧 直接先上链接了 touch me touch me touch me 关于涉及到区间的修改 -- 区间更新的话 分为 增减 或者 修改 主要就是个 laze 标记 就是延迟更新 对于区间更新的写法 一般是有2种 其一 仔细划分到每个细小的区间    另一 粗略划分 反正 ==我的代码里会给出2种写法 看自己喜好 hdu 1 //线段树 成段更新 ---> 替换 根结点的查询 2 3 #i

HDU 4902 线段树(区间更新)

Nice boat Time Limit: 30000/15000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)Total Submission(s): 353    Accepted Submission(s): 169 Problem Description There is an old country and the king fell in love with a devil. The devil alw

HDU 3308 线段树(区间合并)

LCIS Time Limit: 6000/2000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 3896    Accepted Submission(s): 1766 Problem Description Given n integers.You have two operations:U A B: replace the Ath number by B. (index

hdu1754(线段数维护区间最大值)

题意:给定1-n(n<=200000)个数,然后动态改变一些值,并动态询问区间最大值. 解法:裸的线段树,赛前默写模版回忆下线段树代码.仍然要注意:线段树节点数组一定要开到节点数的三倍长度. 代码: /****************************************************** * author:xiefubao *******************************************************/ #pragma comment(lin

poj 3264 Balanced Lineup(线段数求区间最大最小值)

链接:http://poj.org/problem?id=3264 Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 32772   Accepted: 15421 Case Time Limit: 2000MS Description For the daily milking, Farmer John's N cows (1 ≤ N ≤ 50,000) always line up in the same order.

线段树 (区间修改 区间查询 延迟标记)

hdu 1698 Just a Hook 题意: 给你一链子,这天链子由金银铜三种钩子组成,每种钩子都有自己的价值,起初,这条钩子全部由铜钩子组成,给你两个数n(钩子的个数),Q(操作的个数)每次操作就是将给定区间里的数变成某种钩子,求这条链子的总价值. 分析: 线段树模版题,处理好延迟标记即可. 代码: #include<iostream> #include<algorithm> #include<cstdio> #include<cstring> #in

HDU(1698),线段树区间更新

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1698 区间更新重点在于懒惰标记. 当你更新的区间就是整个区间的时候,直接sum[rt] = c*(r-l+1);col[rt] = c:后面的子区间就不管了,当你下次更新某一个区间的时候,把col[rt]从顶往下推(也没有推到底),推到合适的位置,刚好这个位置是我要更新的区间的子区间(可能被横跨了)就停下来. 在这里感谢网上的大牛,感谢杰哥,彬哥.我才能AC. Just a Hook Time Li

HDU 1698 (线段树 区间更新) Just a Hook

有m个操作,每个操作 X Y Z是将区间[X, Y]中的所有的数全部变为Z,最后询问整个区间所有数之和是多少. 区间更新有一个懒惰标记,set[o] = v,表示这个区间所有的数都是v,只有这个区间被分开的时候再往下传递. 1 #include <cstdio> 2 3 const int maxn = 100000 + 10; 4 int sum[maxn << 2], set[maxn << 2]; 5 6 int n, qL, qR, m, v; 7 8 void