线段树求调
查看原帖
线段树求调
306049
Utilokasteinn楼主2023/1/9 12:38

Rt

cov 表示是否被摊平

tag1 是摊平成的数

tag2 是摊平后加的数

tag3 是摊平前最大的加数

tag4 是摊平后最大的(摊平数+加数)

测试点 7,8 已过,应该是区间摊平出问题了。

代码写得可能有点乱,但还是请大佬将就看一下,已经调了半天了。

应该没有人会看完整代码吧,就只发可能错的代码了。

修改代码:

void update_add(int ql,int qr,int k,int p)
{
	if(ql>s[p].r||qr<s[p].l)return;
	if(ql<=s[p].l&&s[p].r<=qr)
	{
		s[p].maxa+=k;
		s[p].maxb=max(s[p].maxb,s[p].maxa);
		s[p].tag2+=k;
		if(!s[p].cov)s[p].tag3=max(s[p].tag3,s[p].tag2);
		else s[p].tag4=max(s[p].tag4,s[p].tag1+s[p].tag2);
		return;
	}
	push_down(p);
	update_add(ql,qr,k,p*2),update_add(ql,qr,k,p*2+1);
	push_up(p);
}
void update_cov(int ql,int qr,int k,int p)
{
	if(ql>s[p].r||qr<s[p].l)return;
	if(ql<=s[p].l&&s[p].r<=qr)
	{
		s[p].maxa=k;
		s[p].maxb=max(s[p].maxb,k);
		s[p].cov=1;
		s[p].tag1=k;
		s[p].tag2=0;
		s[p].tag4=k;
		return;
	}
	push_down(p);
	update_cov(ql,qr,k,p*2),update_cov(ql,qr,k,p*2+1);
	push_up(p);
}

下传代码:

inline void push_down(int p)
{
	if(!s[p].cov)
	{
		int k2=s[p].tag2,k3=s[p].tag3;
		s[p*2].maxb=max(s[p*2].maxb,s[p*2].maxa+k3);
		s[p*2+1].maxb=max(s[p*2+1].maxb,s[p*2+1].maxa+k3);
		s[p*2].maxa+=k2,s[p*2+1].maxa+=k2;
		s[p*2].tag3=max(s[p*2].tag3,s[p*2].tag2+k3);
		s[p*2+1].tag3=max(s[p*2+1].tag3,s[p*2+1].tag2+k3); 
		s[p*2].tag2+=k2,s[p*2+1].tag2+=k2;
		s[p].tag2=s[p].tag3=0;
		return;
	}
	int k1=s[p].tag1,k2=s[p].tag2,k3=s[p].tag3,k4=s[p].tag4;
	
	s[p*2].maxb=max(s[p*2].maxb,s[p*2].maxa+k3);
	s[p*2+1].maxb=max(s[p*2+1].maxb,s[p*2+1].maxa+k3);
	
	s[p*2].tag3=max(s[p*2].tag3,s[p*2].tag2+k3);
	s[p*2+1].tag3=max(s[p*2+1].tag3,s[p*2+1].tag2+k3);
	
	//
	s[p*2].maxa=s[p*2+1].maxa=k1+k2;
	s[p*2].maxb=max(s[p*2].maxb,k4);
	s[p*2+1].maxb=max(s[p*2+1].maxb,k4);
	s[p*2].cov=s[p*2+1].cov=1;
	s[p*2].tag1=s[p*2+1].tag1=k1;
	s[p*2].tag2=s[p*2+1].tag2=k2;
	s[p*2].tag4=s[p*2+1].tag4=k4;

	s[p].cov=s[p].tag1=s[p].tag2=s[p].tag3=s[p].tag4=0;
}

完整代码

2023/1/9 12:38
加载中...