C221110C. SolarPea与网格

news/2024/10/11 22:09:34

C221110C. SolarPea与网格

是怎么想到dp定义的?

思考下面这个情景:

  • 如果一个人在 \(x\), 另一个人在 \(y \ (x \lt y)\), 那么在 \(x\) 的人会把 \(x \lt i \lt y\) 的所有 \(i\) 全走一遍,走完之后 \(x + 1 = y\)

对于这个情景,我们想到记 \(f[i]\) 表示一个人在 \(i - 1\),一个人在 \(i\) ,跳到终点后的max(前一个人得分 减去 后一个人得分)。

我们在转移时,先暂时忽略1,2两个点的贡献。最后加一个 \(a[1] - a[2]\) 就行。

答案: \(f[2]\)

初始化:\(f[n] = 0\)

\(n\) 是最后一步。因此 dp顺序\(n \sim i\) 。有转移:

\[f[i] = \max_{j \gt i} a[j] - (s[i] - s[j - 1]) - f[j] \]

解释一下:由于每次是前一个人先跳,所以他肯定想拿远处很大的一个数(现在不拿就会被对手拿),然后让对手把这一段全部拿掉。最后再把上一步的贡献加上,注意两个人的相对位置翻转了,所以是 \(- f[j]\) 而不是 \(+ f[j]\)

这是最朴素的式子。

答案就是 \(f[2]\)

考虑简化这个式子

我也不知道是怎么注意到可以这么优化的。。。(注意力惊人)

考虑把 \(j \gt i\) 的所有 \(j\) 分成两类:

  • \(j = i + 1\), 则 \(f[i] = a[i + 1] - s[i] + s[i] - f[i + 1] = a[i + 1] - f[i + 1]\)

  • \(j > i + 1\), 则 \(f[i] = \max_{j \gt i + 1} a[j] - s[j - 1] + s[i] - f[j]\)

    ​ 又因为 \(f[i + 1] = \max_{j > i + 1} a[j] - s[j - 1] + s[i + 1] - f[j]\)

    两式相减,则 $f[i + 1] - f[i] = s[i + 1] - s[i] = a[i + 1] $。

    ​ 则 \(f[i] = f[i + 1] - a[i + 1]\)

综上:\(f[i] = |f[i+ 1] - a[i + 1]|\)

考虑利用绝对值的一些性质

\(g[i]\) 表示当 \(a[n] = i\) 时,\(f_2 = g[i]\)

结合上面绝对值的式子,可以得到:

\[|\ |\ |\ |f[n] - a[n]\ | - a[n - 1]\ | - a[n - 2] - \cdots| - a[3]\ | = g[i] = f[2] \]

每增加一个绝对值,对 \(g[i]\) 的影响就是先整体向右平移 \(a[n]\),然后 对于 \(i < a[n]\), 按 \(y\) 轴对称一下。

发现不是很好直接做。考虑用 \(deque\) 维护,每次在把 \(<a[i]\) 的一段元素再插入队首即可。

值域只有 \(10^6\), 可以直接维护。

如果 \(x\) 极大,那直接一步调到最后就可以(因为肯定最优)。

时间复杂度 \(O(\sum_a +q)\)

/*
Think twice, code once
Please check the followings:
1.Array memory
2.Testing sentence
3.if_else condition
4.freopen
5.long long
*/
#include<bits/stdc++.h>
#define F(i,l,r) for(int i(l);i<=(r);++i)
#define G(i,r,l) for(int i(r);i>=(l);--i)
using namespace std;
using ll = long long;
const int N = 2e5 + 5;
const int inf = 1e9;
list<int> g;
int n, q, cnt = 0;
int a[N], s[N], res[N  * 10];
signed main(){
//	freopen("test.in","r",stdin);
//	freopen("game.in","r",stdin);
//	freopen("game.out","w",stdout);ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);cin >> n;F(i, 1, n - 1) cin >> a[i], s[i] = s[i - 1] + a[i];F(i, 0, s[n - 1] - s[2]) g.push_back(i);F(i, 3, n - 1){auto it = g.begin();F(j, 1, a[i]) ++it, g.push_front(*it);//平移指针, 就相当于是平移图像了}for(auto x : g) res[++ cnt] = x;cin >> q;int x;while(q --){cin >> x;if(x + 1 <= cnt) cout << res[x + 1] + a[1] - a[2] << '\n';else cout << (x - s[n - 1] + s[2]) + a[1] - a[2] << '\n';}return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.ryyt.cn/news/70415.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈,一经查实,立即删除!

相关文章

四级平安、吉祥如意、紫气东来

家和万兴济世长,妻贤子孝运恒昌。 南山苍松栖云鹤,东篱梧桐落凤凰。 西川潜龙引紫气,北斗流光降瑞祥。 德高望重仁者寿,恩泽子孙福满堂。为人:谦逊、激情、博学、审问、慎思、明辨、 笃行 学问:纸上得来终觉浅,绝知此事要躬行 为事:工欲善其事,必先利其器。 态…

mac安装ps2023

花了5毛钱从网上找的资源下载的,真累啊,找了好久 https://www.123pan.com/s/65fKVv-fekWA 1、安装时提示error2、包内容中打开install2、错误码501安装错误原因:Mac系统缺少ACC云运行框架,导致安装报错! 3、错误码81adobe create clould 退出登录账号;

密码学承诺之原理和应用 - Kate多项式承诺

主页微信公众号:密码应用技术实战 博客园首页:https://www.cnblogs.com/informatics/ GIT地址:https://github.com/warm3snow简介 多项式承诺是一种实用性比较强的密码学承诺方案,允许一个方(承诺者)向另一个方(验证者)承诺一个多项式的值,而不泄露多项式的具体形式。…

线段树分治略解杂题解析

可能做到好题之后会再更新吧。 总叙 线段树与离线询问结合技巧又被称为线段树分治。 使用线段树分治维护的信息通常会在某一个时间段内出现,要求在离线的前提下回答某一个时刻的信息并,则可以考虑使用线段树分治的技巧。 以下是线段树分治的基本模板: change 将信息按时间段…

多校A层冲刺NOIP2024模拟赛05

A. 好数(number) 很容易想到 \(n^3\) 枚举两个,看第三个是否出现,扩展一下,枚举一个,看剩下需要的和是否出现过,提前处理出两两的和 和最早能合出这个数的位置,复杂的 \(O(n^2)\)点击查看代码 #include<bits/stdc++.h> const int maxn=5000+10; using namespace …

二分图全面学习笔记

二分图全面学习笔记 Part1:二分图的定义与判定方法 首先,我们要知道二分图的定义是什么。 二分图的定义 ​ 如果一张无向图的 \(n\) 个节点可以分成 \(A,B\) 两个不相交的非空集合,并且同一个集合之中的两个点之间没有边相连接,那么称该无向图为二分图 (Bipartite Graph) …

解密prompt系列40. LLM推理scaling Law

OpenAI的O-1出现前,其实就有大佬开始分析后面OpenAI的技术路线,其中一个方向就是从Pretrain-scaling,Post-Train-scaling向Inference Scaling的转变,这一章我们挑3篇inference-scaling相关的论文来聊聊,前两篇分别从聚合策略和搜索策略来优化广度推理,最后一篇全面的分析…

浅谈一类动态开点线段树优化 - DEST树

前言 线段树,是一种优秀的数据结构,其应用极为广泛。其中,动态开点值域线段树,配合上线段树合并,甚至能替代或超越平衡树。但是,这种线段树的树高与值域相关,很容易产生四五倍常数。无论考虑时间或空间复杂度,这样的树都不算优。那么,我们是否能想办法优化它呢? 优化…