解题思路:
这一题与前面做的线段树的题目有所不同的就是这个子节点不一定一致(有可能子节点有节点的num值小于P),这样就不好进行优化,这里引用max,min两个变量用来储存该节点的子节点的最大值和最小值。若max<p,就可以+c,min>=P,就可以+2*c,这样子节点就可以不用进行+c操作了,这样就可以进行偷懒了。
#include <iostream>
using namespace std;
#define INF 200010
struct Node
{
int r,l,mid,num,max,min;
}node[4*INF];
int P;
int MAX(int a,int b)
{
if(a>b)
return a;
return b;
}
int MIN(int a,int b)
{
return a<b?a:b;
}
void init(int a,int b,int n)
{
node[n].l=a;
node[n].r=b;
node[n].mid=(a+b)/2;
node[n].num=0;
node[n].max=0;
node[n].min=0;
if(a==b)
return;
init(a,(a+b)/2,n*2);
init((a+b)/2+1,b,2*n+1);
}
void update(int a,int b,int c,int n)
{
if(node[n].l==a && node[n].r==b)
{
if(node[n].min>=P)
{
node[n].num+=2*c;
node[n].min+=2*c;
node[n].max+=2*c;
return;
}
if(node[n].max<P)
{
node[n].num+=c;
node[n].min+=c;
node[n].max+=c;
return;
}
}
if(node[n].num)
{
node[2*n].num+=node[n].num;
node[2*n+1].num+=node[n].num;
node[2*n].max+=node[n].num;
node[2*n].min+=node[n].num;
node[2*n+1].max+=node[n].num;
node[2*n+1].min+=node[n].num;
node[n].num=0;
}
if(b<=node[n].mid)
{
update(a,b,c,2*n);
}
else
{
if(a>node[n].mid)
{
update(a,b,c,2*n+1);
}
else
{
update(a,node[n].mid,c,2*n);
update(node[n].mid+1,b,c,2*n+1);
}
}
node[n].max=MAX(node[n*2].max,node[2*n+1].max);
node[n].min=MIN(node[n*2].min,node[n*2+1].min);
}
void print(int n)
{
if(node[n].r==node[n].l)
{
if(node[n].l!=1)
printf(" ");
printf("%d",node[n].num);
return ;
}
if(node[n].num)
{
node[n*2].num+=node[n].num;
node[2*n+1].num+=node[n].num;
node[n].num=0;
}
print(2*n);
print(2*n+1);
}
int main()
{
int n,m;
while(scanf("%d%d%d",&n,&m,&P)!=EOF)
{
int a,b,c;
init(1,n,1);
while(m--)
{
scanf("%d%d%d",&a,&b,&c);
update(a,b,c,1);
}
print(1);
printf("\n");
}
return 0;
}
注意:print函数中:
if(node[n].num)
{
node[n*2].num+=node[n].num;
node[2*n+1].num+=node[n].num;
node[n].num=0;
}
不能省略。