1 条题解

  • 1
    @ 2026-6-12 16:09:48

    个人思路,中间绕了亿下弯,建议别看,亦被烫到

    先考虑每条线段的贡献是否好算,

    对于一条线段,与其他线段的关系有三种

    • 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
    上传者