11.20 CW 模拟赛 赛时记录
看题#
前言: 花了
#
艹, 再一次缺失大样例
神秘博弈放
手玩几组数据大概能做, 后面再认真看
#
看到树直接小命不保
喵了个咪的, 这我打鸡毛啊
又开始想树形
好的方面是,
#
坏了, 今天是神秘
#
没啥思路, 多半最后也只有时间过来打个暴力
正序开题
#
最多想
以下将 dogenya
称为 A
, dogwang
称为 B
注意到 A
每次必定是从序列中删除掉一个数, 使得序列中元素和最大的连续区间元素和最小, 而 B
只能将元素和最大的连续区间选完
关于 B
选择的原因:
如果 B
留一段, 后面一定不优, 一定不如直接选完
也就是说, 这个博弈问题只与 A
有关, 我们每次枚举最小分割点, 前缀和优化查询, 这是
先在这里造数据
in:
10
11 32 14 56 12 37 41 47 24 53
out:
215
就这样
希望别假, 还是先去打
#
如果
现在只过去了
首先观察到, 对于链的情况是一个简单贪心
对于小数据, 我们显然可以
部分分还是非常宽松的, 爽
注意到时间其实就是询问最小的武力值
令
答案二分可得
状态转移方程, 显然的
看起来这并不像一道树形
既然收货不需要时间, 那么我们显然可以在外层二分武力值 , 内层循环中, 能走的全部走即可, 直接用
易得外层
那么正解就出来了, 时间复杂度
这下只过去了
#
直接不打代码冲
先转化题意
每个物品重量
对于第
询问怎样分组, 费用最少
也许是一种很典的
转移过程中记录最后一组的
每次对于一个物品无非两种选择
- 新开一组
- 跟上上一组
但是这样不好设计状态, 只能打
感觉很冷, 要趋势力
想到
令
显然有
有,
这是
#
把暴力当正解想, 这场就结束了
这个题的目标就是把
最多想到
差不多就这样
代码#
#
先打保险一点的
#include <bits/stdc++.h>
#define int long long
const int MAXN = 520; // 641
int n;
int Sum[MAXN];
void solve()
{
int Ans = 0;
int Left = 1, Right = n;
while (Left <= Right)
{
int CutPoint = -1;
int type = -1; // 0 左, 1 右
int Min_Sum = 0x3f3f3f3f;
for (int i = Left; i <= Right; i++) {
if (Min_Sum > std::max(Sum[i - 1] - Sum[Left - 1], Sum[Right] - Sum[i])) {
Min_Sum = std::max(Sum[i - 1] - Sum[Left - 1], Sum[Right] - Sum[i]);
if (Sum[i - 1] - Sum[Left - 1] > Sum[Right] - Sum[i]) type = 0;
else type = 1;
CutPoint = i;
}
}
Ans += Min_Sum;
if (type == 0) Left = CutPoint + 1;
else Right = CutPoint - 1;
}
printf("%lld", Ans);
}
signed main()
{
#ifdef FILE_IO
freopen("number.in", "r", stdin);
freopen("number.out", "w", stdout);
#endif
scanf("%lld", &n);
for (int i = 1; i <= n; i++) {
scanf("%lld", &Sum[i]);
Sum[i] += Sum[i - 1];
}
solve();
return 0;
}
应该不会有太大问题
#
顺下去打, 看看有没有实现上的问题?
#include <bits/stdc++.h>
#define int long long
const int MAXN = 1e6 + 20;
int n, W;
int MaxW = 0;
class Tree_Class
{
private:
public:
struct node
{
int to, w;
int next;
} Edge[MAXN];
int Edge_Cnt = 0;
int head[MAXN];
int Val[MAXN];
void head_init() { for (int i = 0; i <= n + 1; i++) head[i] = -1; }
void addedge(int u, int v, int w) {
Edge[++Edge_Cnt].to = v, Edge[Edge_Cnt].w = w;
Edge[Edge_Cnt].next = head[u];
head[u] = Edge_Cnt;
}
/*建树*/
void solve()
{
for (int i = 2; i <= n; i++)
scanf("%lld", &Val[i]);
for (int i = 1; i <= n - 1; i++) {
int u, v, w;
scanf("%lld %lld %lld", &u, &v, &w);
MaxW = std::max(MaxW, w);
addedge(u, v, w);
}
}
} Tree;
class Sol_Class
{
private:
int f[MAXN];
void dfs(int Now, int fa, int x)
{
f[Now] = Tree.Val[Now];
for (int i = Tree.head[Now]; ~i; i = Tree.Edge[i].next)
{
int NowTo = Tree.Edge[i].to, NowW = Tree.Edge[i].w;
if(NowW > x || NowTo == fa) continue;
dfs(NowTo, Now, x);
f[Now] += f[NowTo];
}
}
bool check(int x) {
memset(f, 0, sizeof(f));
dfs(1, -1, x);
return f[1] >= W;
}
public:
/*二分答案*/
void bin_search()
{
int Left = 0, Right = MaxW + 1;
int Ans;
while (Left < Right) {
int Mid = Left + ((Right - Left) >> 1);
if (check(Mid)) {
Right = Mid;
Ans = Mid;
}else {
Left = Mid + 1;
}
}
printf("%lld", Ans);
}
} Sol;
signed main()
{
#ifdef FILE_IO
freopen("collect.in", "r", stdin);
freopen("collect.out", "w", stdout);
#endif
scanf("%lld %lld", &n, &W);
Tree.head_init();
Tree.solve();
Sol.bin_search();
return 0;
}
应该是对的, 希望别挂
#
这个题需要先捋一捋, 还剩下约
冲冲冲
#include <bits/stdc++.h>
#define int long long
const int MAXN = 1e5 + 20;
int n, W;
int Val[MAXN];
int Sum[MAXN];
class ST_Class
{
private:
int LOG2[MAXN];
int ST_max[MAXN][30], ST_min[MAXN][30];
public:
/*建立 ST 表*/
void solve()
{
LOG2[0] = -1;
for (int i = 1; i <= 1e5; i++) {
LOG2[i] = LOG2[i >> 1] + 1;
}
for (int i = 1; i <= n; i++) {
ST_max[i][0] = ST_min[i][0] = Val[i];
}
int p = log2(n);
for (int k = 1; k <= p; k++) {
for (int s = 1; s + (1 << k) <= n + 1; s++) {
ST_max[s][k] = std::max(ST_max[s][k - 1], ST_max[s + (1 << (k - 1))][k - 1]);
ST_min[s][k] = std::min(ST_min[s][k - 1], ST_min[s + (1 << (k - 1))][k - 1]);
}
}
}
int query_max(int Left, int Right) {
int k = LOG2[Right - Left + 1];
return std::max(ST_max[Left][k], ST_max[Right - (1 << k) + 1][k]);
}
int query_min(int Left, int Right) {
int k = LOG2[Right - Left + 1];
return std::min(ST_min[Left][k], ST_min[Right - (1 << k) + 1][k]);
}
} ST;
struct node
{
int Val;
int Num;
} dp[MAXN];
int Cost(int Left, int Right, int num) {
if (Sum[Right] - Sum[Left - 1] > W) return 0x3f3f3f3f;
return num * (Sum[Right] - Sum[Left - 1]) + ST.query_max(Left, Right) - ST.query_min(Left, Right);
}
/*dp 计算*/
void solve()
{
memset(dp, 0x3f, sizeof(dp));
dp[0] = {0, 0};
for (int i = 1; i <= n; i++) {
for (int j = 0; j < i; j++) {
if (dp[j].Val + Cost(j + 1, i, dp[j].Num + 1) < dp[i].Val) {
dp[i].Val = dp[j].Val + Cost(j + 1, i, dp[j].Num + 1), dp[i].Num = dp[j].Num + 1;
}
}
}
printf("%lld", dp[n].Val);
}
signed main()
{
#ifdef FILE_IO
freopen("grouping.in", "r", stdin);
freopen("grouping.out", "w", stdout);
#endif
scanf("%lld %lld", &n, &W);
for (int i = 1; i <= n; i++)
scanf("%lld", &Val[i]), Sum[i] = Sum[i - 1] + Val[i];
ST.solve();
solve();
return 0;
}
方程有可能会挂
#
这个暴力看手速了
最后也没写完, 太难搞了
baidu 搜索: dfs 计算四元环的个数
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】