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\) 开头的零个或多个字符和结尾的零个或多个字符后得到的字符串。
例如,AB是ABC的子串,但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;
}

浙公网安备 33010602011771号