1 条题解
-
1
个人思路,中间绕了亿下弯,建议别看,亦被烫到
先考虑每条线段的贡献是否好算,
对于一条线段,与其他线段的关系有三种
- 1、相交(不包含)
- 2、不相交
- 3、包含
先粗略设想一下,从左往右枚举线段,向右找一个终点,使当前线段左端点和终点能通过选一些线段来连通成一个,然后连不到的随便选然后发现这不是一般的蠢货能想出来的......首先是一看就没可做性,然后是时复高,最重要的是根本无法统计最终答案(我竟然认真想了好久,我真的太困了)
正文:
没什么经验,无法一眼瞪出dp,只能先做尝试还在绕弯:
先按右端点排序,分上面三种情况讨论
当前线段为i,f[i]表示考虑1~i线段,必选i的所有情况下的复杂度和
- 1、相交:直接继承
- 2、不相交:继承+所有最右端和 i 不相交的情况个数
- 3、包含:直接继承
所以f[i]=sf(sf表示1~i-1所有线段的f和)+ 2^s(s表示 与i不相交的线段个数)
对吧?
这时我们发现错了,原因在哪呢?
看到 (1 6)、(2 3)、(4 5) 这一组线,转移到(1 6)时答案多1,因为(4 5)转移时把(2 3)+(4 5)算为2,而在(1 6)+(2 3)+(4 5)时继承了这个2,实际应为1
所以我们发现,这种 包含内部 无法处理
那怎么办呢?
我们发现,按照L排序,不存在上述情况
#include<bits/stdc++.h> using namespace std; struct node{ int l,r; bool operator <(const node x)const{ return l<x.l; } }a[100005]; const int P=1e9+7; int n,s[200005];long long p[100005],f[100005],sf; int main() { cin>>n;p[0]=1; for(int i=1;i<=n;i++){ p[i]=p[i-1]*2%P; } for(int i=1;i<=n;i++){ cin>>a[i].l>>a[i].r; s[a[i].r]++; } sort(a+1,a+n+1); for(int i=1;i<=2*n;i++){ s[i]+=s[i-1]; } for(int i=1;i<=n;i++){ f[i]=(sf+p[s[a[i].l]])%P; sf=(sf+f[i])%P; } cout<<sf; return 0; }
信息
- ID
- 245
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 5
- 标签
- (无)
- 递交数
- 22
- 已通过
- 14
- 上传者