#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
#define maxn 200010
struct node
{
int Max,Min;
int flag;
}num[maxn<<2];
int P;
void Down(int rt)
{
if(num[rt].flag)
{
num[rt<<1].Max+=num[rt].flag;
num[rt<<1].Min+=num[rt].flag;
num[rt<<1].flag+=num[rt].flag;
num[rt<<1|1].Max+=num[rt].flag;
num[rt<<1|1].Min+=num[rt].flag;
num[rt<<1|1].flag+=num[rt].flag;
num[rt].flag=0;
}
}
void build(int L,int R,int rt)
{
num[rt].Max=num[rt].Min=num[rt].flag=0;
if(L==R)
return;
int m=(L+R)/2;;
build(L,m,rt<<1);
build(m+1,R,rt<<1|1);
}
void update(int L,int R,int a,int b,int c,int rt)
{
int m=(L+R)/2;
if(L==a&&R==b)
{
if(num[rt].Max<P)
{
num[rt].Max+=c;
num[rt].Min+=c;
num[rt].flag+=c;
return;
}
else if(num[rt].Min>=P)
{
num[rt].Max+=2*c;
num[rt].Min+=2*c;
num[rt].flag+=2*c;
return;
}
Down(rt);
update(a,m,a,m,c,rt<<1);
update(m+1,b,m+1,b,c,rt<<1|1);
num[rt].Max=max(num[rt<<1].Max,num[rt<<1|1].Max);
num[rt].Min=min(num[rt<<1].Min,num[rt<<1|1].Min);
return;
}
Down(rt);
if(b<=m)
update(L,m,a,b,c,rt<<1);
else if(a>m)
update(m+1,R,a,b,c,rt<<1|1);
else
{
update(L,m,a,m,c,rt<<1);
update(m+1,R,m+1,b,c,rt<<1|1);
}
num[rt].Max=max(num[rt<<1].Max,num[rt<<1|1].Max);
num[rt].Min=min(num[rt<<1].Min,num[rt<<1|1].Min);
return;
}
void query(int L,int R,int rt)
{
if(L==R)
{
if(L==1)printf("%d",num[rt].flag);
else printf(" %d",num[rt].flag);
return;
}
Down(rt);
int m=(L+R)/2;
query(L,m,rt<<1);
query(m+1,R,rt<<1|1);
}
int main()
{
int n,m;
int i,j,a,b,c;
while(~scanf("%d %d %d",&n,&m,&P))
{
build(1,n,1);
for(i=1;i<=m;i++)
{
scanf("%d %d %d",&a,&b,&c);
update(1,n,a,b,c,1);
}
query(1,n,1);
printf("\n");
}
return 0;
} 线段树成段更新-杭电4107
最新推荐文章于 2018-11-30 19:47:00 发布
本文介绍了一种使用线段树进行区间更新与查询的优化方法,通过递归地将操作下放至子节点,并利用懒惰传播减少重复计算,实现高效的区间操作。适用于需要频繁进行区间加法更新和查询最大最小值的场景。
1175

被折叠的 条评论
为什么被折叠?



