AtCoder Grand Contest 028
链接
A. Two Abbreviations
B. Removing Blocks
C. Min Cost Cycle
不妨钦定每条边是有向的。这样每个点的两条边分别组成的大小关系定义:00(都是 A 较小的),01(出边 B 较小),10,11。
那么最后形成的环中只可能存在:全部点均为01/10,或者至少一个点为11。
可以发现,只要我们知道每个点的情况,如果存在一种合法构造方案的话,所有满足这类情况的方案都是合法的。
我们想要答案最小,自然想要 的前 小的点都是 00 点。
但是这样并不一定成立,所有我们需要把一些 00 点变成 01 点。可以证明至多选 2 个。
复杂度 。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#define N 200010
#define ll long long
using namespace std;
struct node{
ll a,b;
int c;
bool operator <(const node d)const{return a<d.a;}
}v[N];
bool vis[N];
int s[N];
int main()
{
int n,t=0;
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%lld%lld",&v[t+1].a,&v[t+2].a);
v[t+1].b=v[t+2].b=i;
v[t+1].c=0,v[t+2].c=1;
t+=2;
}
sort(v+1,v+t+1);
long long res=0;
bool have=false;
for(int i=1;i<=n;i++)
{
s[v[i].c]++;
res+=v[i].a;
if(vis[v[i].b]) have=true;
else vis[v[i].b]=true;
}
if(have || s[0]==n || s[1]==n){printf("%lld\n",res);return 0;}
res+=v[n+1].a-v[n].a;
s[v[n].c]--,s[v[n+1].c]++;
if(s[0]==n || s[1]==n){printf("%lld\n",res);return 0;}
if(v[n].b==v[n+1].b) res+=min(v[n+2].a-v[n+1].a,v[n].a-v[n-1].a);
printf("%lld\n",res);
return 0;
}
D. Chords
圆上线段交问题可以转换为序列上区间有交且不包含。
可以发现,只有一个区间内没有一条连出边时,这个区间才会增加 1 的贡献。所以我们只需要统计这样区间的个数即可。
而且可以发现的是,这只和区间内没有被确定的点有关。特别的,如果有奇数个点没有被确定,贡献为 0。
dp 即可,复杂度 。
#include<iostream>
#include<cstdio>
#include<cstring>
#define N 610
#define mod 1000000007
using namespace std;
int f[N][N],g[N],r[N][N];
int mn[N][N],mx[N][N];
int a[N];
int main()
{
int n,m;
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)
{
int u,v;
scanf("%d%d",&u,&v);
a[u]=v,a[v]=u;
}
n*=2;
g[0]=1;
for(int i=2;i<=n;i+=2) g[i]=1ll*g[i-2]*(i-1)%mod;
for(int i=1;i<=n;i++)
for(int j=i;j<=n;j++) r[i][j]=r[i][j-1]+(!a[j]);
for(int i=1;i<=n;i++)
for(int j=i;j<=n;j++) mn[i][j]=a[j] && mn[i][j-1]?min(mn[i][j-1],a[j]):mn[i][j-1]+a[j];
for(int i=1;i<=n;i++)
for(int j=i;j<=n;j++) mx[i][j]=a[j] && mx[i][j-1]?max(mx[i][j-1],a[j]):mx[i][j-1]+a[j];
for(int i=1;i<=n;i++)
for(int j=i;j<=n;j++)
if((!mn[i][j] || mn[i][j]>=i) && (!mx[i][j] || mx[i][j]<=j))
{
f[i][j]=g[r[i][j]];
for(int k=i+1;k<j;k++) f[i][j]=(f[i][j]-1ll*f[i][k]*g[r[k+1][j]]%mod+mod)%mod;
}
int ans=0;
for(int i=1;i<=n;i++)
for(int j=i;j<=n;j++) ans=(ans+1ll*f[i][j]*g[n-m*2-r[i][j]])%mod;
printf("%d\n",ans);
return 0;
}
E. High Elements
看起来是个构造题,但是这个“最小字典序”说明这其实是一道正经题。
本文来自博客园,作者:Flying2018,转载请注明原文链接:https://www.cnblogs.com/Flying2018/p/agc028.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· winform 绘制太阳,地球,月球 运作规律
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理