首页 > 其他分享 >ARC C 题做题记录

ARC C 题做题记录

时间:2023-12-22 21:12:34浏览次数:43  
标签:记录 int 线段 re ARC 做题 端点 区间 define

最后更新时间

2023/12/22

温馨提示

右下角有展开目录索引的功能。

由于是做题记录,所以作为题解的话可能有些地方的表达不是特别好,请见谅。


[ARC104C] Fair Elevator

\(2n\) 个位置,要不重复地填 \(2n\) 个数,所以可以发现题目中给的区间里面带 \(-1\) 的都是没有用的,因为反正最后肯定要填,所以它不能提供任何信息。也就是说只有完整的区间是有用的区间信息,但是给出的端点信息也是有用的,因为它确定了某个位置只能作为左端点或者右端点。

首先在输入的时候排除一些显然无解的情况,然后接下来有两种做法:

  • 发现题目中的限制条件意味着如果一些区间它们有交,那么会形成形如 \([x,y],[x+1,y+1],[x+2,y+2]\dots\) 这样的形式,那么我们考虑假设我们现在要加一个区间 \([l,r]\),怎样判断它加进去是否合法。我们枚举 \(i\in [l,r)\),如果 \(i\) 已经被作为了题目中给出的完整区间的左端点,并且它的右端点不是 \([i+r-l]\)(即违反了我们上面提到的那种形式),就不合法,\(i\) 作为右端点的情况类似。还有就是如果不能存在 \([i,i+r-l]\) 这个区间也是不行的,即 \(i\) 和 \(i+r-l\) 都已经被定为端点了,但它们没有匹配。于是可以 \(O(n^3)\) 暴力处理出每个区间是否合法,然后再 \(O(n^3)\) 暴力做区间 \(dp\),枚举断点看是否能分成左右两个合法区间,答案即是 \(f_{1,2n}\)。
    代码参考这篇题解的实现,懒得写了。

  • 考虑判断一段连续的位置能否被合法地填满,这里只考虑填上文提到的那种相交的形式,因为如果不相交的话显然可以拆开,互不影响。假设我们要填的连续段为 \([l,r]\),记 \(len=r-l+1\),显然此处 \(len\) 应为偶数(保证每个区间左右端点配对),并且里面填的每个区间的长度应为 \(\frac{len}{2}+1\)(想象一下或者动手画一下就明白了)。那么考虑双指针 \(i,j\) 扫,枚举往里面填的区间的左右端点,如果 \(i\) 被确定为了右端点或者 \(j\) 被确定为了左端点或者 \(i,j\) 都被确定了但它们没有配对,那么就是不合法的。扫完之后若仍然合法则合法。然后就可以 \(dp\) 了,记 \(f_i\) 表示是否能合法地填完前缀 \(i\)。转移就枚举前面的 \(j\),如果存在 \(f_j\land Check(j+1,i)\),那么 \(f_i=true\)。

$\texttt{Code}$
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define il inline
#define re register
const int N=205;
int n,a[N],b[N],p[N];
bool f[N];
il int read(){
    re int x=0;re char c=getchar(),f=0;
    while(c<'0'||c>'9') f|=(c=='-'),c=getchar();
    while(c>='0'&&c<='9') x=(x<<3)+(x<<1)+(c&15),c=getchar();
    return f?-x:x;
}
il bool Calc(int l,int r){
    int len=(r-l+1)>>1;
    for(re int i=l,j=l+len;j<=r;i++,j++){
        if(p[i]&&p[j]&&p[i]^p[j])return 0;
        if(p[i]&&b[p[i]]==i)return 0;
        if(p[j]&&a[p[j]]==j)return 0;
    }
    return 1;
}
int main(){
    n=read();
    for(re int i=1;i<=n;i++){
        a[i]=read(),b[i]=read();
        if(a[i]!=-1){
            if(p[a[i]])return puts("No"),0;
            else p[a[i]]=i;
        }
        if(b[i]!=-1){
            if(p[b[i]])return puts("No"),0;
            else p[b[i]]=i;
        }
    }
    f[0]=1;
    for(re int i=2;i<=(n<<1);i++)
        for(re int j=i-2;j>=0;j-=2)
            if(f[j]&&Calc(j+1,i)){
                f[i]=1;
                break;
            }
    puts(f[n<<1]?"Yes":"No");
    return 0;
}

[ARC105C] Camels and Bridge

数据范围提示我们枚举全排列,然后考虑计算一个排列的答案,可以对一段连续的骆驼去 \(check\) 它们在一起通过桥的话至少应该有多少长度,记这些骆驼的总重为 \(sum\),那么显然只有限重 \(\lt sum\) 的桥会产生影响,影响的结果是每个这样的桥的长度都要对这一段骆驼的最短长度贡献一个 \(\max\),然后发现这就是一个前缀 \(\max\) 的形式,那么把桥按照限重从大到小排序,排完序之后处理处前缀 \(\max\),每次我们计算时直接把 \(sum\) 丢进去 \(lower_bound\) 即可。

然后就可以 \(dp\) 了,\(f_i\) 表示考虑前 \(i\) 个骆驼的最短长度,\(f_i=max_{j=1}^{i-1}\{f_j+Calc(j,i)\}\)。

$\texttt{Code}$
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define il inline
#define re register
const int N=10,M=1e5+5;
int n,m,a[N],ans=1e18,l[M],v[M],s[N],f[N];
il int read(){
    re int x=0;re char c=getchar(),f=0;
    while(c<'0'||c>'9') f|=(c=='-'),c=getchar();
    while(c>='0'&&c<='9') x=(x<<3)+(x<<1)+(c&15),c=getchar();
    return f?-x:x;
}
struct bridge{
    int l,v;
}b[M];
il bool cmp(bridge x,bridge y){
    return x.v<y.v;
}
il void check(){
    memset(f,0,sizeof f);
    for(re int i=1;i<=n;i++)s[i]=s[i-1]+a[i];
    for(re int i=2;i<=n;i++)
        for(re int j=1;j<i;j++)
            f[i]=max(f[i],f[j]+l[lower_bound(v+1,v+1+m,s[i]-s[j-1])-v-1]);
    ans=min(ans,f[n]);
}
signed main(){
    // freopen("my.in","r",stdin);
    // freopen("my.out","w",stdout);
    n=read(),m=read();
    int mx=0,mn=1e9;
    for(re int i=1;i<=n;i++)a[i]=read(),mx=max(mx,a[i]);
    for(re int i=1;i<=m;i++)b[i].l=read(),b[i].v=read(),mn=min(mn,b[i].v);
    if(mx>mn)return puts("-1"),0;
    sort(b+1,b+1+m,cmp);
    for(re int i=1;i<=m;i++)l[i]=b[i].l,v[i]=b[i].v;
    for(re int i=1;i<=m;i++)l[i]=max(l[i],l[i-1]);
    sort(a+1,a+1+n);
    do{
        check();
    }while(next_permutation(a+1,a+1+n));
    cout<<ans;
    return 0;
}

[ARC106C] Solutions

先判掉一车无解:

  • \(m\lt 0\) 无解,因为 \(A\) 是正解贪心。

  • \(m=n\) 无解,因为 \(B\) 至少会选一个。

  • \(m=n-1\),说明 \(ansB=1,ansA=n\),此时若 \(n\neq 1\),说明这 \(n\) 条线段互不相交,那么 \(ansB\) 也应为 \(n\),矛盾,所以 \(m=n-1\land n\neq 1\) 时无解。

然后考虑什么时候 \(A\) 会少选。即是按左端点排序之后选到了一个左端点小但右端点巨大的线段,导致它包含了很多线段,然后都不能选了,但是 \(B\) 就可以不选这个线段,去选里面的更多的线段。

于是就显然了。先放一条巨长的线段,再在这个线段里面放 \(m+1\) 条互不相交的小线段,这样 \(A\) 会选到里面的 \(m+1\) 条线段,\(B\) 只会选到这条很长的线段,然后就满足题意了。最后在外面补上 \(n-m-2\) 条互不相交的线段即可。

注意特判 \(m=0\),直接放 \(n\) 条互不相交的线段。

$\texttt{Code}$
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define il inline
#define re register
const int N=2e5,star=5e5;
int n,m;
il int read(){
    re int x=0;re char c=getchar(),f=0;
    while(c<'0'||c>'9') f|=(c=='-'),c=getchar();
    while(c>='0'&&c<='9') x=(x<<3)+(x<<1)+(c&15),c=getchar();
    return f?-x:x;
}
int main(){
    n=read(),m=read();
    if(m<0||m==n||(m==n-1&&n>=2))return puts("-1"),0;
    if(!m){
        for(re int i=1;i<=n;i++)cout<<(i<<1|1)<<' '<<((i+1)<<1)<<'\n';
        return 0;
    }
    cout<<1<<' '<<star<<'\n';
    for(re int i=1;i<=m+1;i++)cout<<(i<<1|1)<<' '<<((i+1)<<1)<<'\n';
    for(re int i=1;i<=n-m-2;i++)cout<<(i<<1|1)+star<<' '<<((i+1)<<1)+star<<'\n';
    return 0;
}

标签:记录,int,线段,re,ARC,做题,端点,区间,define
From: https://www.cnblogs.com/MrcFrst-LRY/p/17922358.html

相关文章

  • 无涯教程-PL/SQL - 记录(Records)
    在本章中,无涯教程将讨论PL/SQL中的记录(Records)。记录是一种数据结构,可以容纳不同种类的数据项。记录由不同的字段组成,类似于数据库表的一行。PL/SQL可以处理以下类型的记录-基于表的记录  (Table-basedrecords)基于游标的记录(Cursor-basedrecords)用户定义的记录(U......
  • 『Git』记录Git相关的问题
    1.代码写一半,发现忘记切换分支了,怎么处理?①使用gitstash命令将当前工作目录中的修改保存起来。这将暂存修改,以便稍后可以应用到其他分支上。②使用gitcheckout命令切换到正确的分支,以继续开发工作。③在切换到正确的分支后使用gitstashpop命令来应用之前暂存的修改,将......
  • 2023最新高级难度Rust面试题,包含答案。刷题必备!记录一下。
    好记性不如烂笔头内容来自面试宝典-高级难度Rust面试题合集问:请解释Rust中的并行计算模型和分布式计算模型。在Rust中,你可以利用语言的并发特性来实现并行计算和分布式计算。虽然这些概念是不同的,但它们可以一起使用以提高系统的性能和扩展性。并行计算并行计算是......
  • 2023最新初级难度Ruby面试题,包含答案。刷题必备!记录一下。
    好记性不如烂笔头内容来自面试宝典-初级难度Ruby面试题合集问:什么是Ruby语言?请简要介绍一下Ruby的特点和用途。Ruby是一种面向对象的、动态类型的脚本语言,由日本人松本行弘(YukihiroMatsumoto)于1993年开发。它的设计目标是简单、易读和易于编写,同时具有强大的功能和优雅......
  • 记录一次jedis连接池没有释放导致的生产问题
    /***占用锁,并设置唯一锁id*@paramlockKey锁key*@return锁id*/publicStringlock(StringlockKey,Integertimeout){//获得jedis实例Jedisjedis=redisUtil.getJedis();//锁id(必须拥有此id才能释放锁)StringlockId=UUID.randomUUID().to......
  • Signal信号记录
    Signal信号记录在POSIX.1-1990标准中定义的信号列表信号值动作说明SIGHUP1Term终端控制进程结束(终端连接断开)SIGINT2Term用户发送INTR字符(Ctrl+C)触发SIGQUIT3Core用户发送QUIT字符(Ctrl+/)触发SIGILL4Core非法指令(程序错误、试图执行数据......
  • 记录--Vue3问题:如何实现组件拖拽实时预览功能?
    这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助1.需求分析实现一个CMS内容管理系统,在后台进行内容编辑,在官网更新展示内容。关于后台的编辑功能,大致分为两部分:组件拖拽预览、组件内容编辑实时预览。对于组件拖拽预览,用户可以在含有各种功能组件的列表中,选择......
  • 基于Docker安装Elasticsearch + Kibana
    基于Docker安装Elasticsearch+Kibana前提是先安装好Docker的环境Docker创建网络Docker创建一个网络专门连接Elasticsearch和Kibanadockernetworkcreatees-netDocker安装Elasticsearch拉取镜像(这里以8.6.0版本为例)dockerpullelasticsearch:8.6.0创建es的挂......
  • Spring学习记录之Spring的入门程序
    Spring学习记录之Spring的入门程序前言这篇文章是我第二次学习b站老杜的spring相关课程所进行的学习记录,算是对课程内容及笔记的二次整理,以自己的理解方式进行二次记录,其中理解可能存在错误,欢迎且接受各位大佬们的批评指正;关于本笔记,只是我对于相关知识遗忘时快速查阅了解使用......
  • [问题记录] C# 使用NPOI操作Excel模版写入数据 - 生成文件打开时提示 "发现 XXX.xlsx
    解决方案:1.先确保原来的模版文件打开是正常的,没有提示要恢复2.用Office打开这个模版文件,另存为一个文件。用这个文件来作为模版使用。 问题描述:使用C#NPOI操作Excel模版(模版用office打开是正常的),写入数据,导出的文件打开时提示是否尝试恢复,点击“是”后,发现Excel内......