Codeforces Round 980 (Div. 2) 题解(A-D)
Codeforces Round 980 (Div. 2)
A
思路
推方程式即可, 勉强算贪心吧.
需要使得 a−x 最小, 那么 x 就需要最小, 而满足题目条件, 需要
- a−x≥b−2x
得出x≥b−a, 又因为需要a最大, 所以x=b−a, ans=b−x=2a−b.
但是要注意, 如果a已经大于b, 或者a无法满足营利, 要输出对应结果.
code
void func(void)
{
int a,b;
cin >> a >> b;
if(a >= b) cout << a << '\n';
else
{
int ans = (2*a - b);
cout << (ans >= 0 ? ans : 0) << '\n';
}
}
B
思路
因为只知道每组数目, 但不知道对应关系. 所以每次对不确定为 0 的按钮点击一次, 直到一次不出货.
那么可以用二分查找分界点, 也可以用桶模拟.
每次处理当前不确定为0的, 都减去min(ai), 同时获得cnt(不确定为0总数)×(min(ai)−上次确定为0)瓶水, 次数加上获得水数+此次变为0个数, 因为确定他们变成0需要多一次操作.
wa原因
有一个式子没有删掉导致wa三发
code
void func(void)
{
int n,k;
cin >> n >> k;
map<int,int> cnt;
for(int i=0;i<n;++i)
{
int stp; cin >> stp;
cnt[stp] ++;
}
int stp = 0,lst = 0,times = 0;
for(auto &i : cnt)
{
if((n-stp)*(i.x - lst) >= k)
{
times += k+cnt[lst];
break;
}
else
{
k -= (n-stp)*(i.x - lst);
times += (n-stp)*(i.x - lst) + cnt[lst];
stp += i.y;
lst = i.x;
}
}
cout << times << '\n';
}
C
思路
抽象题
根据两个数中较小的排序, 然后则不受影响了.
当时赌根据两个数和排序还对了.
wa原因
赌根据第一个数排序, 实际应该根据较小数排序.
code
void func(void)
{
int n;
cin >> n;
vector<PII> a(n);
for(auto &i : a) cin >> i.x >> i.y;
sort(a.begin(),a.end(),cmp);
for(auto &i : a) cout << i.x << ' ' << i.y << ' ';
cout << '\n';
}
D
思路
这题可以用最短路, 也可以线段树维护dp.
因为不记得最短路了, 所以用线段树维护dp.
这题纯粹模拟太难, 所以可以维护无法使用, 也就是skip
的点, 使之最小. 然后用一段的前缀和减去被skip
的点.
那么dp[i]
就维护到dp[i]
被skip
的点的总值最小的路径的值.
对于每个点:
- 如果bi>i, 他可以向右移动. 获取更多的点.
- 如果bi<i, 他可以向左移动, 可以确定, 向左移动不如从这个点开始解题得分, 因为解题后只能继续解左边的点.
所以每个点只会从右边的一个点, 或者bi的点移动而来.
又因为由右边移动而来不是被skip
, 所以只需继承到此点的dp
.
那么每个点i查询能到达i的点(j)到i的区间内dp
的最小值,
dpi=dpk+aj(j≤k≤i−1).
对于区间最小值, 可以用线段树维护(st表无法修改)
只需维护单点修改和区间查询
未ac原因
思路不对, 想用朴素的递推或者dfs解答.
code
#include<bits/stdc++.h>
#define Start cin.tie(0), cout.tie(0), ios::sync_with_stdio(false)
#define PII pair<int,int>
#define x first
#define y second
#define ull unsigned long long
#define int long long
using namespace std;
struct data
{
int x,y,z;
bool operator < (const data &i) const
{
return(x == i.x ? (y == i.y ? z < i.z : y < i.z) : x < i.x);
}
};
const int M = 1e18+7;
const int N = 4e5 + 10;
int n;
vector<int> t(N<<2);
void push_up(int p)
{
t[p] = min(t[p<<1],t[p<<1|1]);
}
void modity(int k,int z,int be=1,int ed=n,int p=1)
{
if(k == be && be == ed)
{
t[p] = z;
return ;
}
int mid = (be+ed) >> 1;
if(k <= mid) modity(k,z,be,mid,p<<1);
else modity(k,z,mid+1,ed,p<<1|1);
push_up(p);
}
int query(int l,int r,int be=1,int ed=n,int p=1)
{
if(l <= be && ed <= r) return t[p];
int mid = (be+ed) >> 1,res = M;
if(l <= mid) res = min(res,query(l,r,be,mid,p<<1));
if(mid+1 <= r) res = min(res,query(l,r,mid+1,ed,p<<1|1));
return res;
}
void func(void);
signed main(void)
{
Start;
int _ ; cin >> _;
while(_--) func();
return 0;
}
void func(void)
{
cin >> n;
vector<int> a(n+1),s(n+1),b(n+1);
vector<vector<int>> vis(n+1);
for(int i=1;i<=n;++i)
{
cin >> a[i];
s[i] = s[i-1] + a[i];
}
for(int i=1;i<=n;++i)
{
cin >> b[i];
if(b[i] > i) vis[b[i]].push_back(i);
}
// for(int i=0;i<=n;++i) dp[i] = M;
for(int i=0;i<=(n<<2)+10;++i) t[i] = M;
modity(1,0);
for(int i=2;i<=n;++i)
{
int dp = M;
for(auto &j : vis[i])
{
dp = min(dp,query(j,i-1)+a[j]);
}
modity(i,dp);
}
int ans = -M;
for(int i=1;i<=n;++i)
{
ans = max(ans,s[i] - query(i,i));
}
cout << ans << '\n';
}
分类:
题解 / CFround
, 题解
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· 使用C#创建一个MCP客户端
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· Windows编程----内核对象竟然如此简单?