APIO2009 会议中心

洛谷3626传送门

 

Description:

给定一些区间,求最多不相交的区间数,并且输出字典序最小的选择方案

 

Solution:   f(l,r)表示[l,r]中的最多不相交的区间数

这题好难啊 好难想也好难写qwq 然后这里的solution写得有点语无伦次了

最多不相交的区间数贪心很好求

直接求字典序最小的方案好像不太可行 如果我们按字典序枚举并且判断是否可以加入答案就好了

其实就是这样的啊(强行带入)

我们现在要想怎么判断某区间是否可以加入答案

如图,有一些区间,现在我们要判断红色区间是否可以加入答案

找到红色区间左边第一个和右边第一个与它不相交的区间

如果f(r1+1,l3-1)==f(r1+1,l2-1)+f(r2+1,l3-1)+1即可以加入答案

发现我们需要频繁的求解f(l,r)

所以如果再像以前那样朴素地求肯定不行

我们可以优化一下 以前我们排序后一个个枚举其实就是为了找到下一个与当前选择不相交的区间

而这样的下一个是确定的 于是就用倍增啦 f[i][j]表示i后面的第2j个区间的编号

最后还要注意一点

对于下图这种情况 求最多不相交区间数时明显选择1区间比2区间优 于是我们要把2区间去掉

所以有了code里的b[]

 

CODE:

 1 #include<bits/stdc++.h>
 2 #define rg register
 3 #define go(i,a,b) for(rg int i=a;i<=b;++i)
 4 #define yes(i,a,b) for(rg int i=a;i>=b;--i)
 5 #define inf 1e9
 6 #define il inline
 7 using namespace std;
 8 int rd()
 9 {
10     int x=0,y=1;char c=getchar();
11     while(c<'0'||c>'9'){if(c=='-')y=-1;c=getchar();}
12     while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+c-'0';c=getchar();}
13     return x*y;
14 }
15 const int N=500005;
16 struct node
17 {
18     int l,r;
19     il bool operator <(node x)const
20     {return r==x.r?l>x.l:r<x.r;}
21 }a[N],b[N],c[N];
22 int ans,n,ct,f[N][20],L[N],R[N];
23 il int calc(int l,int r)
24 {
25     rg int sm=1,nw=lower_bound(L+1,L+ct+1,l)-L;
26     if(nw>ct||R[nw]>r)return 0;
27     yes(i,19,0)if(f[nw][i]&&R[f[nw][i]]<=r)nw=f[nw][i],sm+=1<<i;
28     return sm;
29 }
30 set<node> q;
31 int main()
32 {
33     freopen("1.in","r",stdin);
34     freopen("1.out","w",stdout);
35     n=rd();go(i,1,n)a[i].l=rd(),a[i].r=rd(),c[i]=a[i];
36     sort(a+1,a+n+1);
37     go(i,1,n)if(!ct||a[i].l>b[ct].l)b[++ct]=a[i];
38     go(i,1,ct)
39     {
40         int j=i;
41         while(b[j].l<=b[i].r&&j<=ct) j++;if(j>ct)continue;
42         f[i][0]=j;
43     }
44     go(j,1,19)
45         go(i,1,ct)f[i][j]=f[f[i][j-1]][j-1];
46     go(i,1,ct)L[i]=b[i].l,R[i]=b[i].r;
47     ans=calc(0,inf);printf("%d\n",ans);
48     set<node>:: iterator x,y;
49     q.insert((node){0,0});q.insert((node){inf,inf});
50     go(i,1,n)a[i]=c[i];
51     go(i,1,n)
52     {
53         x=y=q.lower_bound(a[i]);x--;
54         rg int l=x->r,r=y->l;
55         if(l>=a[i].l||r<=a[i].r)continue;
56         if(calc(l+1,r-1)==calc(l+1,a[i].l-1)+calc(a[i].r+1,r-1)+1)
57         {printf("%d ",i);q.insert(a[i]);}
58     }
59     return 0;
60 }
View Code

 

posted @ 2019-02-15 15:23  DTTTTTTT  阅读(152)  评论(0编辑  收藏  举报