首页 > 其他分享 >USACO2023 Bronze 题解

USACO2023 Bronze 题解

时间:2023-01-31 00:23:01浏览次数:43  
标签:USACO2023 include 字符 int 题解 leq mathsf 奶牛 Bronze

Problem 1. Leaders

\(\mathcal{Farmer \ John}\) 共有 \(n\) 头奶牛,品种用字符 \(\mathsf{G}\) 或 \(\mathsf{H}\) 表示。每一头牛有一个管辖区间 \([i , E_i]\)
称一头奶牛为领袖,仅当其能管辖所有与自己同品种的奶牛,或者能管辖另一种奶牛的领袖,或者二者都满足。
在两种奶牛中各选出一只作领袖,问可能的领袖对数。
\(2 \leq n \leq 10^{5}\) ,数据保证有解。

先统计能管辖到所有奶牛的领袖对 \((p,q)\) ,共有两种情况 \((p < q)\):

  1. \(p,q\) 均能管辖到同品种的所有奶牛
    显然这样的 \((p,q)\) 最多有一对。
    用前缀和预处理出 \(preG_i\) 表示前 \(i\) 只奶牛中品种为 \(\mathsf{G}\) 的数量,\(preH_i\) 表示前 \(i\) 只奶牛中品种为 \(\mathsf{H}\) 的数量。
    于是可以 \(O(1)\) 求出 \([i , E_i]\) 中与自己同品种奶牛的数量,判断其是否等于总共的同品种奶牛数量即可。

  2. \(q\) 能管辖同品种的所有奶牛,\(p\) 能管辖到 \(q\)
    利用情况 \(1\) 中的性质,每种奶牛中 \(q\) 最多有一个。所以可以记录下 \(q\) ,然后枚举 \(p\) ,统计 \(q\) 出现在多少个异种奶牛管辖区间即可。

#include<cstdio>
const int M=1e5+10;

char str[M];
int n,E[M],preG[M],preH[M];
long long ans;

int main(){
    scanf("%d",&n);
    scanf(" %s",str+1);
    for(int i=1;i<=n;i++) scanf("%d",&E[i]);

    for(int i=1;i<=n;i++){//前缀和
        preG[i]=preG[i-1],preH[i]=preH[i-1];
        if(str[i]=='G') preG[i]++;
        if(str[i]=='H') preH[i]++;
    }
    int totG=preG[n],totH=preH[n];//总共的 G,H 数量

    int curG=-1,curH=-1;
    for(int i=1;i<=n;i++){
        if(str[i]=='G' and preG[E[i]]-preG[i-1]==totG) curG=i;
        if(str[i]=='H' and preH[E[i]]-preH[i-1]==totH) curH=i;
    }
    if(curG!=-1 and curH!=-1) ans++;//第一种情况

    if(curG!=-1)
        for(int i=1;i<curG;i++)
            if(curG<=E[i]) ans++;
    if(curH!=-1)
        for(int i=1;i<curH;i++)
            if(curH<=E[i]) ans++;//第二种情况
    printf("%lld",ans);
    return 0;
}

Problem 2. Air Cownditioning II

\(\mathcal{Farmer \ John}\) 的 \(n\) 只奶牛住在编号 \(1...100\) 的牛棚里。第 \(i\) 头奶牛住在 \([s_i , t_i]\) 牛棚中。每头奶牛的居住范围不相交。
天气炎热,第 \(i\) 头奶牛希望自己居住的牛棚温度全部下降至少 \(c_i\) 度。
有 \(m\) 台空调,第 \(j\) 台空调能用 \(cost_j\) 的代价使 \([a_j , b_j]\) 牛棚下降 \(p_j\) 度。
问满足所有奶牛的最小花费是多少。
\(1 \leq n \leq 20\) , \(1 \leq m \leq 10\) , 数据保证有解。

数据范围十分小,考虑二进制枚举每台空调用或不用。

先处理出第 \(i\) 个牛棚至少需要下降 \(lim_i\) 度。

然后枚举状态 \(S \in [0 , 2^m)\) ,若二进制下 \(S\) 的第 \(j\) 位为 \(1\) 代表使用这台空调,\(0\) 则不用。

维护一个数列,若使用第 \(j\) 台空调则将 \([a_j , b_j]\) 区间都加上 \(p_j\) ,显然可以用 \(差分 + 前缀和\) 维护。

最后判断方案是否合法。合法则将花费与答案取最小值。

其实可以用 \(dfs\) ,但是二进制枚举代码更简洁所以用了后者。

#include<cstdio>
#include<cstring>
const int M=110;

int max(int A,int B){return A>B?A:B;}
int min(int A,int B){return A<B?A:B;}

int n,m;
int s[M],t[M],c[M],lim[M];
//第 i 个位置至少要降低lim[i] 度
int cost[M],p[M],a[M],b[M];

int dif[M],pre[M];
bool check(){
    pre[0]=0;
    for(int i=1;i<=100;i++) pre[i]=pre[i-1]+dif[i];
    for(int i=1;i<=100;i++)
        if(pre[i]<lim[i]) return false;
    return true;
}

int main(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++) scanf("%d%d%d",&s[i],&t[i],&c[i]);
    for(int i=1;i<=m;i++) scanf("%d%d%d%d",&a[i],&b[i],&p[i],&cost[i]);

    for(int i=1;i<=n;i++)
        for(int j=s[i];j<=t[i];j++) lim[j]=max(lim[j],c[i]);
    
    int ans=0x3f3f3f;
    for(int S=0;S<(1<<m);S++){
        memset(dif,0,sizeof dif);
        int tot=0;
        for(int i=1;i<=m;i++)
            if(S&(1<<(i-1))){
                tot+=cost[i];
                dif[a[i]]+=p[i],dif[b[i]+1]-=p[i];
            }
        if(check()) ans=min(ans,tot);
    }
    printf("%d",ans);
    return 0;
}

Problem 3. Moo Operations

给定 \(q\) 个字符串,每个都包含字符 \(\mathsf{M}\) 和 \(\mathsf{O}\) 。
你可以执行若干次以下两种操作,将字符串变成 \(\mathsf{MOO}\) :

  1. 将第一个或最后一个字符取反, \(\mathsf{M} \to \mathsf{O}\) 或者 \(\mathsf{O} \to \mathsf{M}\) 。
  2. 删除第一个或最后一个字符。

对于每个字符串求出最少的操作次数。无解输出 -1
\(1 \leq q \leq 100\) , 字符串长度不大于 \(100\) 。

设最后保留下来的 \(\mathsf{MOO}\) 的中间那个 \(\mathsf{O}\) 在原数列的下标为 \(i\) 。很显然中间的 \(i\) 不可能被改动,所以可以枚举 \(i\) 。

设字符串长度为 \(len\) ,那么要保留上述 \(MOO\) ,需要经过如下操作:

  1. 删除位于 \([1,i-2]\) 的字符。

  2. 删除位于 \([i+2,len]\) 的字符。

  3. 修改 \(i-1\) 与 \(i+1\) 位的字符。

第 \(1,2\) 步共需要操作 \(len - 3\) 步,第三步若第 \(i-1\) 位不为 \(\mathsf{M}\) ,第 \(i+1\) 位不为 \(\mathsf{O}\) 则各需要一次修改。最后与答案取最小值即可。

注意判断无解。

#include<cstdio>
#include<cstring>
#define min(A,B) ((A)<(B)?(A):(B))
const int M=110;

int q;
int main(){
    scanf("%d",&q);
    while(q--){
        bool flag=false;
        char str[M];
        scanf(" %s",str+1);

        int len=strlen(str+1),ans=0x3f3f3f;
        for(int i=2;i<len;i++){
            if(str[i]!='O') continue;
            int tmp=len-3;
            if(str[i-1]=='O') tmp++;
            if(str[i+1]=='M') tmp++;
            ans=min(ans,tmp),flag=true;
        }
        if(flag) printf("%d\n",ans);
        else printf("-1\n");
    }
    return 0;
}

标签:USACO2023,include,字符,int,题解,leq,mathsf,奶牛,Bronze
From: https://www.cnblogs.com/zzxLLL/p/17077610.html

相关文章

  • 算法:线段树&&Luogu p3372题解
    前言不愧是线段树,竟然卡我这么久,还是那句话:十年OI一场空,不开longlong见祖宗#1什么是线段树?线段树长什么样?通俗一点,线段树就是线段,树。实际上,线段树是一棵完全......
  • CF1067E 题解
    题意传送门给定一棵\(n\)个节点的树,每条边有\(\frac{1}{2}\)的概率出现,可以得到一个森林,求这个森林邻接矩阵的秩的期望。\(1\len\le5\times10^5\)。题解此题关键......
  • [AHOI2022] 山河重整 题解
    T3,一个不错的数学题,给了不少的暴力分。Statement求有多少值域为\([1,n]\)的集合,01背包可以凑出\(1\simn\)中的所有数字。Subtask\(1\sim6\)我们从小到大选择每......
  • 微信小程序-【转发好友】以及中文标题乱码问题解决
    微信小程序的转发功能,参考官方文档,使用的buttom的open-type功能,下面是转发功能的具体实现。//通过按钮的open-type="share"实现转发,触发onShareAppMessage函数<butto......
  • 洛谷P2375 [NOI2014] 动物园【题解】
    题目简要对于字符串\(......
  • 部分互测题,专项测试题题解
    互测部分1https://www.cnblogs.com/Chencgy/p/16970117.html2A.营救皮卡丘跑弗洛伊德,搞出\(i->j\)不经过比\(i,j\)编号大的点的最小花费每个点都要走一遍,套......
  • TypeDB Forces 2023 (Div. 1 + Div. 2) 题解
    更新中……A~D略。E.TheHarmonizationofXOR题目链接题意简述\(t\)组testcase,每组给定\(n,k,x\)三个数。求将\(1\simn\)划分成\(k\)个子序列(可以不连......
  • CF1787H Codeforces Scoreboard 题解
    鬼知道怎么会撞题的,甚至是没听过的OJ。首先不考虑对\(a_i\)取\(\max\),显然直接按照\(k\)降序排序最优。接下来考虑\(a_i\)的限制,如果取到了\(a_i\)一定放在最......
  • lg8945题解
    考虑一个20分的\(O(n^2)\)做法:枚举答案区间\([l,r]\),那么显然要把尽可能多的1填入\([l,r]\)。使用前缀和计算\([l,r]\)中\(0\)的个数,那么填入后的价值可以\(O(1)\)计算。......
  • npm ERR! ERESOLVE unable to resolve dependency tree 问题解决
    阅读原文-问题解决与原因分析安装命令增加--legacy-peer-deps修饰npminstall--legacy-peer-deps......