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);
}
离散化
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

浙公网安备 33010602011771号