ABC 441复盘(A-E)

比赛链接

CDE

C 贪心

https://atcoder.jp/contests/abc441/tasks/abc441_c

问题陈述

\(N\) 个杯子,每个杯子都装有一种无色透明的液体。
具体来说, \(ith\) /- \((1\leq i\leq N)\) 杯中有 \(Ai\) 毫升液体。
众所周知,这些杯子中正好有 \(K\) 个装有清酒(米酒),其余的装有水。
但是,不知道哪些杯子装的是清酒。
高桥可以选择一些(一个或多个)杯子,喝掉其中的所有液体。
求无论哪些杯子装有清酒,要保证他至少喝 \(X\) 毫升清酒,他至少需要选择多少个杯子?
如果不可能做出这样的选择,请打印 \(-1\)

思路:贪心 假设n-k个都是水 那么在只取了n-k个的时候有可能全部取到清水
因此 我们能确保喝到酒的时候应该取n-k+x杯 其中x是保证为酒的杯数
又因为无法确保所有喝到的酒都是装的最多的杯子 因此要假设x为最小的1-x杯
因此直接排序 求是否能在x杯的时候喝到 否则向后拓展

点击查看代码
void solution::solve()
{
    int n,k,x;cin>>n>>k>>x;
    vector<int> a(n);
    for(int i=0;i<n;i++) cin>>a[i];
    sort(a.rbegin(),a.rend());
    int sum=0,cnt=n-k;
    for(int i=n-k;i<n;i++)
    {
        cnt++;
        sum+=a[i];
        if(sum>=x) return cout<<cnt<<endl,void();
    }
    cout<<-1<<endl;
}

D 模拟 dfs

https://atcoder.jp/contests/abc441/tasks/abc441_d

问题陈述

有一个有向图(不一定简单),图中有 \(N\) 个顶点和 \(M\) 条边,顶点的编号为顶点 \(1, 2, \ldots, N\)
\(i\) -th \((1\leq i\leq M)\) 条边从顶点 \(Ui\) 到顶点 \(Vi\) ,代价为 \(Ci\) 。此外,每个顶点的外度最多为 \(4\)

查找所有顶点 \(v\) \((1\leq v\leq N)\)\((1\leq v\leq N)\) 满足以下条件:

存在一条从顶点 \(1\) 到顶点 \(v\) 的路径,且满足以下两个条件:

  • 它恰好遍历了 \(L\) 条边。如果同一条边被多次遍历,则每次遍历都计算在内。
  • 已遍历边的成本总和至少为 \(S\) ,最多为 \(T\) 。(如果同一条边被多次遍历,则每次遍历的成本都会加到总和中)。
    什么是出度?顶点 \(u\) 的出度指的是从顶点 \(u\) 出发的边的数量。即使多条边指向同一个顶点,也会分别计算。

思路:模拟即可

E 前缀和(?)

问题陈述

给你一个长度为 \(N\) 的字符串 \(S\) ,它由三种字符组成:A"、"B "和 "C"。
\(S\) 中有 \(\dfrac{N(N+1)}2\) 个非空连续子串。求其中包含的A多于B的个数。
请注意,如果两个子串取自 \(S\) 中的不同位置,即使它们是相等的字符串,也要分别计算。

什么是子串?
\(S\)子串是删除 \(S\) 开头的零个或多个字符和结尾的零个或多个字符后得到的字符串。
例如,ABABC的子串,但AC不是ABC的子串。

思路:
首先 容易得到 假设Ai和Bi为1-i的A的个数和B的个数的前缀和
那么当i-j段满足条件的情况下 应该令Aj-A(i-1)>Bj-B(i-1)
令Di=Ai-Bi 也就是求当i<j时 Di<Dj的情况
题解代码主要是在固定右端点 记录当j固定时候 在此之前出现的可行方案
也就是通过数组d来记录Di出现的次数

点击查看代码
void solution::solve()
{
    int n;cin>>n;
    string s;cin>>s;
    int sum=0;
    //严格小于当前pos值的所有pos值的个数
    vi d(2*n+1,0);
    int pos=n;
    //前i个字符中a-b的个数+N
    //pos=N是为了计入单字符
    d[pos]++;
    int ans=0;
    for(int i=0;i<n;i++)
    {
        if(s[i]=='A') sum+=d[pos++];
        //当pos增加 补上pos的数量
        //先加再升pos
        if(s[i]=='B') sum-=d[--pos];
        //当pos减少 减去pos-1的数量
        //先降pos再减 因为是严格小于pos
        d[pos]++;
        ans+=sum;
        cout<<s[i]<<" "<<ans<<endl;
    }
    cout<<ans<<endl;
}
posted @ 2026-01-30 16:53  无限ovo  阅读(1)  评论(0)    收藏  举报