[HAOI2014] 贴海报
因为后贴的海报可以覆盖前面已贴的海报或部分海报,所以我们倒序贴海报
一个海报可以被看见,只有在他所在的区间内至少有一格没有被贴上海报
我们可以将贴海报的过程想象成在一段区间上染色,当我们考虑一个新海报时,我们只需要判断他所在区间内有没有还没被染上色的格子,然后将他所在区间全部染上色,这个过程是可以用线段树优化
对于线段树的每一个节点,我们记录他有没有被完全染上色,查询时当查询到一个被完全染上色的节点后直接返回就行,而修改时就正常区间修改就行
注意:区间范围过大需要离散化
AC代码
using namespace std;
#define ll long long
#define MAXN 4010
#define bl bool
inline ll read(){
ll x=0,f=1;
char c=getchar();
while(c<'0'||c>'9'){
if(c=='-')f=-1;
c=getchar();
}
while(c>='0'&&c<='9'){
x=x*10+c-'0';
c=getchar();
}
return x*f;
}
struct node{
bl tag[MAXN*4];
ll l[MAXN*4],r[MAXN*4];
void push_up(ll now){
tag[now]=tag[now*2]&tag[now*2+1];
}
void build(ll now,ll lz,ll rz){
l[now]=lz,r[now]=rz;
if(lz==rz)return;
ll mid=(lz+rz)/2;
build(now*2,lz,mid);
build(now*2+1,mid+1,rz);
}
void ad(ll now,ll lz,ll rz){
if(tag[now])return;
if(l[now]>=lz&&r[now]<=rz){
tag[now]=1;
return;
}
ll mid=(l[now]+r[now])/2;
if(lz<=mid)ad(now*2,lz,rz);
if(rz>mid)ad(now*2+1,lz,rz);
push_up(now);
}
bl re(ll now,ll lz,ll rz){
if(tag[now])return 0;
if(l[now]>=lz&&r[now]<=rz)return 1;
ll mid=(l[now]+r[now])/2,ans=0;
if(lz<=mid)ans|=re(now*2,lz,rz);
if(rz>mid)ans|=re(now*2+1,lz,rz);
return ans;
}
};
bool cmp(ll a,ll b){
return a>b;
}
struct node_has{
ll pre[MAXN];
ll siz;
void insert(ll x){
pre[++siz]=x;
}
void mk(){
sort(pre+1,pre+1+siz);
ll _siz=siz;
for(ll i=1;i<=_siz;i++){
if(pre[i]==pre[i+1]){
pre[i]=0;
siz--;
}
}
sort(pre+1,pre+1+_siz,cmp);
sort(pre+1,pre+1+siz);
}
ll find(ll x){
ll l=1,r=siz;
while(l<r){
ll mid=(l+r+1)/2;
if(pre[mid]<=x)l=mid;
else r=mid-1;
}
return l;
}
}has;
ll n,m,ans;
ll l[MAXN],r[MAXN];
node tr;
int main(){
n=read(),m=read();
// tr.build(1,1,n);
for(ll i=1;i<=m;i++){
l[i]=read(),r[i]=read();
has.insert(l[i]),has.insert(r[i]);
has.insert(r[i]+1),has.insert(l[i]-1);
}
has.mk();
tr.build(1,1,has.siz);
for(ll i=m;i;i--){
l[i]=has.find(l[i]),r[i]=has.find(r[i]);
// cout<<l[i]<<" "<<r[i]<<endl;
if(tr.re(1,l[i],r[i]))ans++;
tr.ad(1,l[i],r[i]);
}
cout<<ans<<endl;
return 0;
}

浙公网安备 33010602011771号