1 条题解
-
0
自动搬运
来自洛谷,原作者为

李至擎
**搬运于
2025-08-24 22:51:12,当前版本为作者最后更新于2023-11-22 21:51:58,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
“这不是简单题吗,为什么是黑啊?”——marblue
记位置 会对答案产生贡献当且仅当 ,问题可以转化成在 个点中选最多的贡献给答案,现在考虑限制。对于两个区间 ,我们分情况讨论一下:
-
。显然我们先执行 再执行 不劣。
-
。显然互不影响。
-
。令 ,如果 在后面则 会产生贡献,否则 会产生贡献。所以 与 不能同时选择,这就是一个建图后的独立集。
发现题目保证 互不相等,故这是一个二分图,跑 bitset 优化 dinic/匈牙利即可,复杂度 $\mathcal{O}(\dfrac{n^3}{w})/\mathcal{O}(\dfrac{n^2\sqrt{n}}{w})$。似乎还可以用可持久化线段树优化建图的 dinic,好像是 ,但我不太会(
是 luogu 上的倒数第二劣解,不知道为什么 dinic 这么慢啊,可能复杂度假了?
证明一下为什么找到独立集后一定有对应解。无解当且仅当对于区间执行顺序的先后限制构成环。考虑找到这个环上随便一个区间 ,假设它取的是右端点 产生贡献,找到它下一个区间 ,,此时只能是 产生贡献。于是递归下去,因为 互不相同,所以环上的区间的 单调递增,故不会形成环。
#include<bits/stdc++.h> using namespace std; const int inf=1e9; inline int read(){ int x=0,f=1;char ch=getchar(); while (!isdigit(ch)){if (ch=='-') f=-1;ch=getchar();} while (isdigit(ch)){x=x*10+ch-48;ch=getchar();} return x*f; } int n,S,T,dep[10005];bitset<10005>g[10005]; int bfs(){ for(int i=1;i<=T;i++)dep[i]=0; dep[S]=1;queue<int>q;q.push(S); while(!q.empty()){ int u=q.front();q.pop(); for(int v=g[u]._Find_first();v<=T;v=max(v+1,(int)g[u]._Find_next(v))){ if(g[u][v]==0)continue; if(!dep[v])dep[v]=dep[u]+1,q.push(v); } } return dep[T]; } int dinic(int u,int flow){ if(u==T)return flow; int rest=0; for(int v=g[u]._Find_first();v<=T&&flow;v=max(v+1,(int)g[u]._Find_next(v))){ if(g[u][v]==0)break; if(dep[v]!=dep[u]+1)continue; int k=dinic(v,min(flow,1));if(!k)dep[v]=0; rest+=k,flow-=k;if(k)g[u][v]=0,g[v][u]=1; } return rest; } int l[5005],r[5005],pos[10005]; signed main(){ n=read(),S=2*n+1,T=2*n+2; for(int i=1;i<=n;i++){ l[i]=read(),r[i]=read(); pos[l[i]]=0,pos[r[i]]=1; } for(int i=1;i<=n;i++){ for(int j=1;j<=n;j++){ if(l[i]<l[j]&&l[j]<r[i]&&r[i]<r[j]){ g[l[j]][r[i]]=1; } } } for(int i=1;i<=2*n;i++)if(pos[i]==0)g[S][i]=1; for(int i=1;i<=2*n;i++)if(pos[i]==1)g[i][T]=1; int ans=2*n; while(bfs())ans-=dinic(S,inf); printf("%d\n",ans); return 0; } -
- 1
信息
- ID
- 9251
- 时间
- 3000ms
- 内存
- 16MiB
- 难度
- 7
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者