P2205

P2205[USACO13JAN] 刷墙 Painting the Fence S
分析该题,Bessie每走一次,相等于给\([last,now]\)标记一次,有\(n\)次标记,
由于该题是标记,又有区间修改,考虑线段树
注:具体分析看注释

$build$&$struct$
struct Segment_tree{
    int l;//左端点
    int r;//右端点
    int cover;//该区间被【整个】覆盖的次数
    int tag;//lazy_tag
};
void build(int u,int l,int r){
	t[u].l=l,t[u].r=r;
	if(l==r) return ;
	int mid=l+r>>1;
	build(u<<1,l,mid);
	build(u<<1|1,mid+1,r);
}

因为\(cover\)是整个被覆盖的次数,所以不需要\(pushup\)

$pushdown$&$update$
void pushdown(int u){
	if(t[u].tag){
		t[u<<1].tag+=t[u].tag;//懒标记下传
		t[u<<1|1].tag+=t[u].tag;
		t[u<<1].cover+=t[u].tag;//如果u被覆盖了x次,那u<<1,u<<1|1都会被覆盖x次
		t[u<<1|1].cover+=t[u].tag;
		t[u].tag=0;//清空
	}
}
void update(int u,int l,int r,int x){
	if(t[u].l>=l&&t[u].r<=r){
		t[u].cover+=x;
		t[u].tag+=x;
		return ;
	}pushdown(u);
	if(t[u<<1].r>=l) update(u<<1,l,r,x);
	if(t[u<<1|1].l<=r) update(u<<1|1,l,r,x);
}
因为Bessie可能到达$1e9$的位置上,考虑离散化 ,记录Bessie每走一次所到达的位置
离散化
for(int i=1;i<=n;i++){
	int x;char op;cin>>x>>op;
	if(op=='L') now-=x;//now记录当前位置
	if(op=='R') now+=x;
	Q[i]=now;
	pla[i]=now;//离散化
}
sort(pla,pla+n+1);
int len=unique(pla,pla+n+1)-(pla);
build(1,0,len);
Q[0]=lower_bound(pla,pla+len,Q[0])-pla;
for(int i=1;i<=n;i++){
	Q[i]=lower_bound(pla,pla+len,Q[i])-pla;
	int left=min(Q[i],Q[i-1]),right=max(Q[i],Q[i-1]);
	update(1,left,right,1);//
}
接下来是询问,这个就比较简单了
询问
int ask(int u){
	if(t[u].cover>=k)
		return pla[t[u].r]-pla[t[u].l];
	if(t[u].l==t[u].r) return 0;
	pushdown(u);
	return ask(u<<1)+ask(u<<1|1);
}

上述代码明显是错误的,为什么
我们之前做过矩形面积并,在那道题中,直接写\(l,r\)同样错误,因为我们在离散化时将原本不连续的点变得连续,这就导致相邻两点之间的位置被忽略了,所以我们用\([l,r]\)指代\([l,r+1]\),这样就解决了问题

AC Code

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+17;
int pla[N],now,n,k,Q[N];
struct node{
	int l,r,cover,tag;
}t[N<<2];
void build(int u,int l,int r){
	t[u].l=l,t[u].r=r;
	if(l==r) return ;
	int mid=l+r>>1;
	build(u<<1,l,mid);
	build(u<<1|1,mid+1,r);
}
void pushdown(int u){
	if(t[u].tag){
		t[u<<1].tag+=t[u].tag;
		t[u<<1|1].tag+=t[u].tag;
		t[u<<1].cover+=t[u].tag;
		t[u<<1|1].cover+=t[u].tag;
		t[u].tag=0;
	}
}
void update(int u,int l,int r,int x){
	if(t[u].l>=l&&t[u].r<=r){
		t[u].cover+=x;
		t[u].tag+=x;
		return ;
	}pushdown(u);
	if(t[u<<1].r>=l) update(u<<1,l,r,x);
	if(t[u<<1|1].l<=r) update(u<<1|1,l,r,x);
}
int ask(int u){
	if(t[u].cover>=k)
		return pla[t[u].r+1]-pla[t[u].l];//不要忘记r指代r+1
	if(t[u].l==t[u].r) return 0;
	pushdown(u);
	return ask(u<<1)+ask(u<<1|1);
}
int main(){
	cin>>n>>k;
	pla[0]=0,Q[0]=0;
	for(int i=1;i<=n;i++){
		int x;char op;cin>>x>>op;
		if(op=='L') now-=x;
		if(op=='R') now+=x;
		Q[i]=now;
		pla[i]=now;
	}
	sort(pla,pla+n+1);
	int len=unique(pla,pla+n+1)-(pla);
	build(1,0,len-1);
	Q[0]=lower_bound(pla,pla+len,Q[0])-pla;
	for(int i=1;i<=n;i++){
		Q[i]=lower_bound(pla,pla+len,Q[i])-pla;
		int left=min(Q[i],Q[i-1]),right=max(Q[i],Q[i-1]);
		update(1,left,right-1,1);//r->r+1
	}
	cout<<ask(1);
	return 0;
}
//l->r l->r+1 
posted @ 2026-04-11 20:09  Underthetwilight  阅读(4)  评论(0)    收藏  举报