AtCoder Grand Contest 028

链接

A. Two Abbreviations

skipped

B. Removing Blocks

skipped

C. Min Cost Cycle

不妨钦定每条边是有向的。这样每个点的两条边分别组成的大小关系定义:00(都是 A 较小的),01(出边 B 较小),10,11。

那么最后形成的环中只可能存在:全部点均为01/10,或者至少一个点为11。

可以发现,只要我们知道每个点的情况,如果存在一种合法构造方案的话,所有满足这类情况的方案都是合法的。

我们想要答案最小,自然想要 a 的前 n2 小的点都是 00 点。

但是这样并不一定成立,所有我们需要把一些 00 点变成 01 点。可以证明至多选 2 个。

复杂度 O(nlogn)

#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 即可,复杂度 O(n3)

#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

看起来是个构造题,但是这个“最小字典序”说明这其实是一道正经题。

posted @   Flying2018  阅读(5)  评论(0编辑  收藏  举报
(评论功能已被禁用)
编辑推荐:
· 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编程运行原理
点击右上角即可分享
微信分享提示