首页 > 其他分享 >CF1851 部分题解

CF1851 部分题解

时间:2023-09-08 10:48:00浏览次数:48  
标签:CF1851 200005 int 题解 奇偶性 read 即可 序列 部分

2023-07-30 19:35:02

前言

因为我实在是太菜了,没时间也不会做最后两题,所以这里只有前 \(5\) 道签到题的题解。

之后我有时间看了后两题的题解再来更新吧~

A

先不用看那么多七七八八的,搞清楚下面几点即可:

  • 高度不能相同。
  • 高度差得被整除。
  • 高度差不能太大。
    好了,然后就可以 \(AC\) 了。

\(Code\)

int T,n,m,k,H,tot;
int main(){
    T=read();
    while(T--){
        n=read(),m=read(),k=read(),H=read(),tot=0;
        for(int i=1;i<=n;i++){
            int h=abs(H-read());
            if(h!=0&&h%k==0&&h/k<m)tot++;
        }
        printf("%d\n",tot);
    }
}

B

题意

给定序列,可以交换奇偶性相同的数字,问你最后可不可以交换成单调不降序列。

因为奇偶性不同是不可能换到位置相同的,即每个位置的奇偶性是固定的,只要在不改变位置奇偶性的状态下可以任意交换的,所以我们只需要保留序号排个序然后看排序之后自己原来位置填的是否是奇偶性相同的即可。

\(Code\)

typedef pair<int,int> PII;
int T,n,b[200005];
PII a[200005];
bool check(){
    for(int i=1;i<=n;i++)if((a[i].first&1)^(b[i]&1))return 0;
    return 1;
}
int main(){
    T=read();
    while(T--){
        n=read();
        for(int i=1;i<=n;i++){
            a[i].first=read();
            a[i].second=i;
            b[i]=a[i].first;
        }
        sort(a+1,a+1+n);
        if(check())puts("YES");
        else puts("NO");
    }
}

C

题意

你可以按顺序取出包含若干个色块的序列,序列必须包含第一块和最后一块,然后将其分割成若干个数量均为 \(k\) 的部分,每个部分的颜色必须一样,不同部分之间颜色可以一样,问你能否找到这样一个序列。

我们从第一块和最后一块必须选入手,实际上我们也只需要考虑最前一段和最后一段是否能顺序凑到 \(k\) 个即可。

因为无论中间如何选,最后选出的序列必然包含首尾段,所以我们实际上可以忽略中间的部分,用两个指针分别从前往后和从后往前扫一遍,判断前面和后面的段是否可以有超过 \(k\) 个颜色相同即可。

注意一些特判,比如当首尾颜色相同时只需要一段连起来即可。

\(Code\)

int T,n,c[200005],k;
bool check(){
    int l,r,tl=0,tr=0;
    for(r=1;r<=n;r++){
        if(c[r]==c[1])tr++;
        if(tr==k)break;
    }
    if(tr<k)return 0;
    for(l=n;l;--l){
        if(c[l]==c[n])tl++;
        if(tl==k)break;
    }
    if(tl<k)return 0;
    if(c[1]==c[n])return 1;
    if(r>l)return 0;
    return 1;
}
int main(){
    T=read();
    while(T--){
        n=read(),k=read();
        for(int i=1;i<=n;i++){
            c[i]=read();
        }
        if(check())puts("YES");
        else puts("NO");
    }
}

D

题意

给你一个前缀和数组,但是缺少了一个数值,问原数组能否是 \(n\) 的排列。

思路

首先遇到前缀和数组当然得先给它差分一下得到一个序列了,我们看到样例 \(4\),发现当少的是最后一个时,可以得到一个 \(n-1\) 的排列,这里特判即可。

那其他情况呢?在差分之后我们会发现 \([1,n]\) 至少少了两个值,可能会出现一个在 \([1,n]\) 中重复的,也可能出现 \(\le n\) 的,但是因为前缀和最后一个值不变,所以原序列的和也不变,故少的两个值必然相加等于那个不正常的值。

相应的,当少的数超过两个或者不正常的数不止一个,那么就不可能组成一个排列。

细节很多,结合代码理解更佳。

\(Code\)

int T,n;
ll a[200005];
bool pd[200005];
bool check(){
    ll los1=0,los2=0,mor=0;//los 少的数,mor是不正常的数
    for(int i=n-1;i;--i){
        a[i]-=a[i-1];
        if(a[i]>n||pd[a[i]]){
            if(mor)return 0;//不止一个不正常
            mor=a[i];
            continue;
        }
        pd[a[i]]=1;
    }
    for(int i=1;i<=n;i++){
        if(!pd[i]){
            if(!los1)los1=i;
            else if(!los2)los2=i;
            else return 0;//少的不止两个
        }
    }
    if(!los2&&!mor)return 1;//少的是最后一个值的情况
    if(los1+los2!=mor)return 0;//不相同也不行
    return 1;
}
int main(){
    T=read();
    while(T--){
        n=read();
        for(int i=1;i<n;i++){
            a[i]=read();
            pd[i]=0;
        }
        pd[n]=0;
        if(check())puts("YES");
        else puts("NO");
    }
}

E

第一眼以为是连边跑个最短路,没想到比跑最短路还简单。

由于一种魔药可以由其他的药合成,而且没有自己到的自己的方法,显然是个 DAG,可以用拓扑序一个个搞,但是我懒得打,直接跑个记搜即可。

关注到有无限的魔药,赋值为 \(0\) 即可,不能被合成的直接赋值成原价格,对于可以被合成的,我们向下搜索找价值,然后把总价格与自己的价格比较即可。

\(Code\)

int T,n,k,a[200005];
ll f[200005];
vector<int>F[200005];
ll dfs(int x){
    if(f[x]!=-1)return f[x];
    ll ans=0;
    for(int y:F[x]){
        ans+=dfs(y);
    }
    return f[x]=min(ans,1ll*a[x]);
}
int main(){
    T=read();
    while(T--){
        n=read(),k=read();
        for(int i=1;i<=n;i++){
            a[i]=read();
            f[i]=-1;
            F[i].clear();
        }
        for(int i=1;i<=k;i++){
            int p=read();
            a[p]=0;
            f[p]=0;
        }
        for(int i=1;i<=n;i++){
            int m=read();
            for(int j=1;j<=m;j++){
                int u=read();
                if(!a[i])continue;
                F[i].push_back(u);
            }
            if(!m)f[i]=a[i];
        }
        for(int i=1;i<=n;i++){
            printf("%lld ",dfs(i));
        }
        puts("");
    }
}

标签:CF1851,200005,int,题解,奇偶性,read,即可,序列,部分
From: https://www.cnblogs.com/NBest/p/17686898.html

相关文章

  • 暑假集训Day19 比赛题解
    2023-08-0516:22:13总结这次打下来,由于T2贪心不够完全,T3模拟\(5\)个时不是最优,T4想到暴力做法但是来不及打,加之全都是捆绑测试点,导致我T2,T3虽然加起来有不少点对了,但是还是判全错,最后也只剩下T1的100。感觉这次前三题也不难,都是可做的,T4的30pts暴力也很白给,但......
  • 暑假集训 Day17 模拟赛题解
    2023-08-0318:18:03前言好家伙,很少完整订正一场比赛,可能是因为这个比赛相对来说确实不难吧(至少正解不难)。总结与反思这场比赛其实没有我想象的那么难,只是觉得题目可能不简单,就没有往简单的思路想,反而是被之前讲过的题疑惑,以为要用到一些很奇特的算法,结果打完以后看了题解再结......
  • UVA10368 题解
    2023-08-0615:18:08solution双倍经验这种有限轮游戏的博弈通常都是有两种状态,必胜态和必败态。对于必胜态,指的是从它可以转移到必败态。对于必败态,指的是从它不论如何只能转移到必胜态。对于每个玩家都采取最优策略的有限游戏,我们通常只需要关注必胜态与必败态之间的转移即......
  • 【题解】AtCoder Regular Contest 162
    A.EkidenRace题目描述:有\(n\)个人参加了往返赛跑,每个人有一个编号\(1\)到\(n\)。已知以下信息:如果按照往路的成绩排序,那么任何两个人的成绩都不相同。同时第\(i\)个人在往路中排名第\(i\)。如果按照往返的成绩排序,那么任何两个人的成绩都不相同。同时第\(i\)个人......
  • 用函数公式统计小数部分的位数!
    1职场实例小伙伴们大家好,今天我们来解决一个公众号关注者后台留言咨询的一个问题:如何利用Excel函数公式统计小数部分的位数。基于这个问题呢,小编整理了一下解题思路,并且可以带大家温习几个基础的常用的函数用法。如下图所示:A列为我们将要统计原始数据,我们发现所有的数值均带小数点,......
  • P9189 [USACO23OPEN] Custodial Cleanup G 题解
    Description奶牛旅馆可以被看作一个\(N\)个节点\(M\)条边的无向简单图,其中每个房间有一个颜色\(C_i\),以及一个钥匙,颜色为\(S_i\),FJ最初在\(1\)号节点,手上一把钥匙都没有。FJ可以进行无数次以下操作:捡起当前房间的钥匙。(FJ可以同时手持多个钥匙)将部分或全部手......
  • All Pairs Maximum Flow题解
    前置知识:1.P3376【模板】网络最大流2.P4897【模板】最小割树(Gomory-HuTree)Ebola有一句很著名的话如果你乱搞过了我请你抽烟那么这道题肯定不能普通的dinic直接水过去,不然就不是紫题了,那么直接祭出最小割树,复杂度\(O(Tn^3m)\),但是因为dinic跑不满,所以是可以过的。......
  • 韬客时代卷轴模式系统开发介绍和部分核心源码
    韬客时代是一种卷轴模式系统。什么是卷轴模式呢?新用户注册,先送你一部分积分,该积分用于兑换一个初始任务,俗称卷轴!卷轴模式的赚钱的原理是,你用积分兑换初级任务包,完成卷轴任务之后,你可以获得更多的积分,然后复投,达到一定数量后可以兑换更高级的任务包,任务包越高级每次获得的积分也就越......
  • [题解] AtCoder Beginner Contest 308 A~G
    AtCoderBeginnerContest308A~GA.NewSchemevoidMain(){vector<i64>a(8);for(auto&x:a)cin>>x;if(!is_sorted(a.begin(),a.end())&&!all_of(a.begin(),a.end(),[](auto&x){returnx%25!=0||!(100......
  • CF1374E2 Reading Books(hard version) 题解
    CF1374E2ReadingBooks(hardversion)这道题是在CF1374E1ReadingBooks(easyversion)的基础上出的,而且仅仅增加了一个\(m\)的限制,下面的做法也是基于简单版的思路而想到的。建议先尝试简单版,然后尝试此题。题意简述:有\(n\)本书,每本书有一个阅读时间\(t_i\),和属性\(......