题解:AT_arc190_a [ARC190A] Inside or Outside

· · 题解

以此纪念我唯一一场 ARC 唯一一道做出来的题。

思路

题意不再赘述。我们把输出的第一行,也就是“代价”,叫做 cost。我们按照 cost 从小到大讨论。

首先,如果 cost=1,那么必然有一个区间满足 l=1,r=n,除此以外不会有其它 cost=1 的情况。

其次,我们特判一堆 cost=2 的情况。如果有两个区间 [l_1,r_1][l_2,r_2] 满足:

现在只剩一个 cost=3 的情况了。排除了前面所有情况之后,剩下的区间按照左端点排序,必然像这样:

我们把这些区间从上到下标号为 1,2,...,m。我们发现,只要对 1 号区间进行 1 操作,2 号区间进行 2 操作,m 号区间进行 1 操作,那么所有点都可以被覆盖到,就像这样:

发现 2 区间外每一个点都被覆盖到了,区间内的每一个点也都被覆盖到了。

这就是 cost=3 的情况。欸,那什么时候无解呢?在理论 cost=3 的情况中,如果 m=2,那么只有两个相交但不包含的区间,这时无论对这两个区间怎么操作都是无法覆盖整个序列的,所以无解。

代码实现

$cost=2$ 的情况,我们先把区间按照左端点排序,那么如果 $r_1<l_m$,就变成了 $cost=2$ 的第一种情况。 考虑一下怎么判断包含。还记得我们是怎么判断二维偏序的吗?对于 $(l_1,r_1),(l_2,r_2),\dots,(l_k,r_k)$,我们先按照 $l$ 排序,然后依次把 $r_1,r_2,\dots,r_k$ 加到树状数组中。这次我们先把区间排序了,然后我们把二维偏序反过来做,依次把 $r_m,r_{m-1},\dots,r_1$ 加入树状数组中来判断包含关系。这样就判掉了第二种情况。 除去这两种情况以后,区间 $1$ 和区间 $m$ 肯定是相交而不包含的关系,所以如果 $l_1=1,r_m=n$,就变成了第三种情况。 剩下的就是 $cost=3$ 的情况了,只用判断一个 $m\le 2$ 就可以了。 ### 示例代码 ```cpp #include<cstdio> #include<algorithm> using namespace std; const int MAXN=2e5+10; int n,m; struct INTERVAL{ int l,r; int id; }a[MAXN]; namespace BIT{ int c[MAXN<<3]; #define lowbit(x) (x)&(-(x)) void add(int x){ while(x<=n){ ++c[x]; x+=lowbit(x); } } int query(int x){ int res=0; while(x){ res+=c[x]; x-=lowbit(x); } return res; } } using BIT::query; using BIT::add; inline int check_inside(){ for(int i=m;i>=1;--i){ if(query(a[i].r)){ return i;//返回:包含其他区间的区间是哪个区间 } add(a[i].r); } return 0; } int ans[MAXN]; int main(){ scanf("%d%d",&n,&m); for(int i=1;i<=m;++i){ scanf("%d%d",&a[i].l,&a[i].r); a[i].id=i; if(a[i].l==1&&a[i].r==n){ putchar('1');putchar('\n');//cost=1的情况 for(int j=1;j<=m;++j){ j==i?putchar('1'):putchar('0'); putchar(' '); } return 0; } } sort(a+1,a+m+1,[&](INTERVAL H,INTERVAL G){return H.l==G.l?H.r<G.r:H.l<G.l;}); if(a[1].r<a[m].l){//两个区间相互分离 putchar('2');putchar('\n');ans[a[1].id]=2; ans[a[m].id]=2; } else{ int p=check_inside(); if(p){//存在区间相互包含的情况 bool flag=false; putchar('2');putchar('\n'); for(int i=1;i<=m;++i){ if(i==p){ ans[a[i].id]=1; } else if((!flag)&&(a[i].l>=a[p].l&&a[i].r<=a[p].r)){ ans[a[i].id]=2; flag=true; } } } else{ if(a[1].l==1&&a[m].r==n){ putchar('2');putchar('\n');ans[a[1].id]=1; ans[a[m].id]=1; } else{ if(m<=2){ putchar('-');putchar('1'); return 0; } else{ putchar('3');putchar('\n'); ans[a[1].id]=1; ans[a[2].id]=2; ans[a[m].id]=1; } } } } for(int i=1;i<=m;++i){ putchar(ans[i]|'0');putchar(' '); } return 0; } ```