20241110

T1

前缀后缀

首先 \(q\) 的数据范围是在搞笑,因为最多 \(n\) 次操作之后序列就没了。然后可以考虑 \(f_{l, r}\) 表示还剩 \([l, r]\) 时最多执行到了哪个操作。转移考虑下一个操作在左边做还是在右边做即可。可以对每个询问预处理出每个点左右第一个能接这个询问的点。时间复杂度 \(\mathcal{O}(n^2)\)

代码
#include <iostream>
using namespace std;
inline void Cmax(int& x, int y) { x = max(x, y); }
bool bg;
int n, q;
int mn[5005][5005];
int d[5005], s[5005];
int tor[5005][5005], tol[5005][5005];
int dp[5005][5005];
int a[5005];
bool ed;
int main() {cerr << (&ed - &bg) / 1024.0 / 1024.0 << "\n";freopen("presuf.in", "r", stdin);freopen("presuf.out", "w", stdout);cin >> n >> q, q = min(n, q);for (int i = 1; i <= n; i++) cin >> a[i], mn[i][i] = a[i];for (int i = 1; i <= n; i++) {for (int j = i + 1; j <= n; j++) mn[i][j] = min(mn[i][j - 1], a[j]);}for (int i = 1; i <= q; i++) cin >> d[i] >> s[i];for (int j = 1; j <= q; j++) {for (int i = d[j]; i <= n; i++) tol[i][j] = ((mn[i - d[j] + 1][i] >= s[j]) ? i : tol[i - 1][j]);tor[n + 1][j] = n + 1;for (int i = n; i; i--) tor[i][j] = ((i + d[j] - 1 <= n && mn[i][i + d[j] - 1] >= s[j]) ? i : tor[i + 1][j]);}int ans = 0;for (int d = n; d; d--) {for (int l = 1, r = d; r <= n; l++, ++r) {int v = dp[l][r] + 1;if (tor[l][v] + ::d[v] - 1 <= r) Cmax(dp[tor[l][v] + ::d[v]][r], v);if (tol[r][v] - ::d[v] + 1 >= l) Cmax(dp[l][tol[r][v] - ::d[v]], v);}}for (int i = 1; i <= n; i++) {for (int j = 1; j <= n; j++) Cmax(ans, dp[i][j]);}cout << ans << "\n";return 0;
}

T2

拉起窗帘

首先容易发现最优策略一定是先把所有的窗帘都降到一个高度之下,然后直接开电动。这样对每一个限高就会存在一个最优的阈值。设限高为 \(r\),阈值为 \(b\) 时的答案为 \(f(r, b)\),注意到其由两部分组成,第一部分是手动把最大的砍下来的时间,第二部分是自动的时间。会发现当限高 \(r\) 固定时,随着 \(b\) 的增加,两部分都是下凸函数,因此它们的和也是下凸函数。到这里就可以直接二分做了,复杂度就是单 \(\log\),但是如果打表就会发现这个下凸的极值点随着 \(r\) 的增加存在决策单调性。因此可以直接维护两个指针扫,复杂度就是 \(\mathcal{O}(n)\)

代码
#include <iostream>
#define int long long
using namespace std;
int n, t, s, K, q;
int cnt[100005], ans[100005], pre[100005], suf[100005];
int Suf[100005], a[100005];
int rt[100005]; // time required for auto to decrease i centimeters
// required height, border
int calc(int r, int b) { return t * (Suf[b] - b * suf[b]) + rt[b - r]; }
signed main() {freopen("curtain.in", "r", stdin);freopen("curtain.out", "w", stdout);cin >> n >> t >> s >> K;for (int i = 1; i <= n; i++) cin >> a[i], cnt[a[i]]++, Suf[a[i]] += a[i];pre[0] = cnt[0];for (int i = 1; i <= 100000; i++) pre[i] = pre[i - 1] + cnt[i];for (int i = 1; i <= 100000; i++) rt[i] = rt[i - 1] + s + K * (pre[i - 1]);for (int i = 100000; ~i; i--) suf[i] = suf[i + 1] + cnt[i], Suf[i] += Suf[i + 1];for (int i = 0; i <= 100000; i++) {ans[i] = (i ? ans[i - 1] : 0);ans[i] = max(ans[i], i);while (ans[i] < 100000 && calc(i, ans[i]) > calc(i, ans[i] + 1)) ++ans[i];}cin >> q;for (int i = 1, x; i <= q; i++) {cin >> x;cout << calc(x, ans[x]) << " ";}cout << "\n";return 0;
}

T3

直径

不难想到构造一个中心点,然后向外连 \(k\) 条边,再在这 \(k\) 条边的另一个端点处各挂一个菊花。这样可以很方便的控制直径的数量:若 \(k = 2\),则直径条数即为两个外挂菊花的叶子数之积。对于 \(k = 3\) 也是同理。通过打表可以发现 \(k = 2, 3\) 即可覆盖 \(n \le 5 \times 10^6\) 的所有情况,因此直接就做完了。

代码
#include <iostream>
using namespace std;
bool v[5000005];
int n;
int main() {freopen("diameter.in", "r", stdin);freopen("diameter.out", "w", stdout);// for (int i = 1; i <= 4996; i++) {//     for (int j = i; i + j <= 4996; j++) {//         for (int k = j; i + j + k <= 4996; k++) {//             if (i * j <= 5000000) //                 v[i * j] = 1;//             if (i * j + j * k + k * i <= 5000000) //                 v[i * j + j * k + k * i] = 1;//         }//     }// }// for (int i = 5000; i <= 5000000; i++) {//     if (!v[i]) //         cout << i << " ";// }// cout << "\n";cin >> n;for (int i = 1; i <= 4998; i++) {for (int j = 1; i + j <= 4998; j++) {if (i * j == n) {cout << i + j + 2 << "\n";cout << "1 2 1\n";for (int a = 1; a <= i; a++) cout << 1 << " " << a + 2 << " 1\n";for (int b = 1; b <= j; b++) cout << 2 << " " << b + i + 2 << " 1\n";return 0;}}}for (int i = 1; i <= 4996; i++) {for (int j = 1; i * j < n && i + j <= 4996; j++) {if ((n - i * j) % (i + j) != 0) continue;int k = (n - i * j) / (i + j);if (i + j + k <= 4996) {cout << i + j + k + 4 << "\n";cout << "1 2 1\n";cout << "1 3 1\n";cout << "1 4 1\n";for (int a = 1; a <= i; a++) cout << 2 << " " << a + 4 << " 1\n";for (int b = 1; b <= j; b++) cout << 3 << " " << b + i + 4 << " 1\n";for (int c = 1; c <= k; c++) cout << 4 << " " << c + i + j + 4 << " 1\n";return 0;}}}return 0;
}

T4

洗澡

首先把人按照 \(t_i\) 排序。先考虑 \(m = 1\),则对于每个 \(s_i\),有显然的下界 \(\max\limits_{1 \le j \le i} \{ t_j + (i - j) \times T \}\)。然后会发现这个下界总是能取到。感性理解的话可以考虑每次等待一定形成一条链,然后每条链的开头会给这条链当中的所有人提供这样的一个下界。因此这个一定可以取到。因此就是要求 \(\sum\limits_{i = 1}^n iT - t_i - \min\limits_{1 \le j \le i} \{ jT - t_j \}\)。前面那个是好搞的,考虑后面的。这就相当于一个求前缀 \(\min\) 的和。发现在 \(i\) 的时间更改之后他的位置可能发生变化。设原位置为 \(x\),新位置为 \(y\)。接下来只讨论 \(x < y\) 的情况,其他是类似的。

我们首先从第一个数开始跳,每次跳到后面第一个小于自己的数,直到下一个数在 \(x\) 之后。然后用当前的前缀最小值跳到 \([x + 1, y - 1]\) 这个区间当中,然后在这个区间里面往后跳,直到下一个数在 \(y\) 之后。然后判断当前前缀最小值和新插入的数的大小关系,再跳到 \([y + 1, n]\) 并跳到最后。这个跳的过程显然可以用倍增优化,要特殊处理的位置只有两个。于是 \(m = 1\) 就做完了。实现上,会发现我们要做的事就是拿着一个前缀最小值跳到区间 \([l, r]\) 中,然后要知道跳出来之后的前缀最小值以及区间内的前缀最小值的和。可以封装为一个函数 \(f(l, r, x)\),这样写起来更方便。

然后考虑 \(m > 1\),发现实际上是把所有人按照 \(\bmod m\) 分组,同一组内是 \(m = 1\) 的子问题,而原问题的答案是所有子问题答案的和。于是对每个模 \(m\) 的同余类开一个上面说的东西维护即可。这个时候就会出现不同等价类中的区间相互轮换的情况,需要特别注意。

代码
#include <iostream>
#include <algorithm>
#include <vector>
#define int long long
using namespace std;
const int inf = 0x7ffffffffffffff;
ostream& operator<<(ostream& out, __int128 x) {if (x == 0) {out << "0";return out;}bool neg = (x < 0);x = (x < 0) ? -x : x;string str;while (x) str += (char)('0' + x % 10), x /= 10;reverse(str.begin(), str.end());if (neg) str = '-' + str;out << str;return out;
}
int n, m, q, T;
int a[1000005], stk[1000005], sz;
struct Data_Structure {int r, n;__int128 ans;vector<signed> tor[20];vector<__int128> a, val[20];void ini(int x) {r = x, n = a.size();a.emplace_back(inf);for (__int128 i = 0, c = inf; i < n; i++) a[i] = i * T - a[i], c = min(c, a[i]), ans += c;for (int i = 0; i < 20; i++) val[i].resize(n + 1), tor[i].resize(n + 1);tor[0][n] = stk[sz = 0] = n;for (int i = n - 1; ~i; i--) {while (sz && a[stk[sz]] > a[i]) --sz;val[0][i] = a[i] * (stk[sz] - i), tor[0][i] = stk[sz];stk[++sz] = i;}for (int i = 1; i < 20; i++) {for (int j = 0; j <= n; j++) {tor[i][j] = tor[i - 1][tor[i - 1][j]];val[i][j] = val[i - 1][j] + val[i - 1][tor[i - 1][j]];}}}pair<__int128, __int128> f(int L, int R, __int128 x, int v = 0) {L = L / m + (L % m > r);R = R / m - (R % m < r);if (L > R) return make_pair(x, (R - L + 1) * v * T);int q = L, p = R + 1;if (a[L] <= x) p = L;else {for (int i = 19; ~i; i--) {if (tor[i][q] > R) continue;if (a[tor[i][q]] <= x) p = tor[i][q];else q = tor[i][q];}}__int128 ret;ret = (p - L) * x;for (int i = 19; ~i; i--) {if (tor[i][p] <= R) ret += val[i][p], p = tor[i][p];}ret += (R - p + 1) * a[p];ret += (R - L + 1) * v * T;return make_pair(min(x, p <= R ? a[p] : inf), ret);}
} ds[5];
__int128 bans;
int V[5];
void fv(__int128& s, __int128& p, __int128 v) { (p <= v) ? (s += p) : (p = v, s += v); }
signed main() {cin >> n >> m >> q >> T;for (int i = 0; i < n; i++) cin >> a[i], ds[i % m].a.emplace_back(a[i]), bans += (i / m) * T - a[i];for (int i = 0; i < m; i++) ds[i].ini(i);while (q--) {int x, v;__int128 tmp = bans, c;__int128 ans = 0;cin >> x >> v, --x;bans += a[x], bans -= v;int y = lower_bound(a, a + n, v) - a;y -= (y > x);if (x == y) {for (int i = 0; i < m; i++) x % m != i ? (ans += ds[i].ans) : 0;pair<__int128, __int128> p = ds[x % m].f(0, x - 1, inf);c = p.first, ans += p.second;fv(ans, c, (x / m) * T - v);p = ds[x % m].f(x + 1, n - 1, c);ans += p.second;} else if (x < y) {for (int i = 0; i < m - 1; i++) {pair<__int128, __int128> p = ds[i].f(0, x - 1, inf); ans += p.second;p = ds[i + 1].f(x + 1, y, p.first); c = p.first; ans += p.second;if (y % m == i) fv(ans, c, (y / m) * T - v);p = ds[i].f(y + 1, n - 1, c); ans += p.second;}pair<__int128, __int128> p = ds[m - 1].f(0, x - 1, inf); ans += p.second;p = ds[0].f(x + 1, y, p.first + T); c = p.first; ans += p.second;if (y % m == m - 1) fv(ans, c, (y / m + 1) * T - v);p = ds[m - 1].f(y + 1, n - 1, c - T); ans += p.second;ans -= T * ((y + 1) / m - x / m);} else {for (int i = 1; i < m; i++) {pair<__int128, __int128> p = ds[i].f(0, y - 1, inf); c = p.first, ans += p.second;if (y % m == i) fv(ans, c, (y / m) * T - v);p = ds[i - 1].f(y, x - 1, c); ans += p.second;p = ds[i].f(x + 1, n - 1, p.first); ans += p.second;}pair<__int128, __int128> p = ds[0].f(0, y - 1, inf); c = p.first, ans += p.second;if (y % m == 0) fv(ans, c, (y / m) * T - v);p = ds[m - 1].f(y, x - 1, c - T, 1); ans += p.second;p = ds[0].f(x + 1, n - 1, p.first + T); ans += p.second;}cout << bans - ans << "\n";bans = tmp;}return 0;
}

T1 想好久不会,后来会的时候感觉唐完了。T3 一开始想到打表验证但是感觉太扯淡,后来打表发现确实是对的。

打表出奇迹。

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Day13 备战CCF-CSP练习

202312-3Day 13 题目描述 题目分析 大模拟,用栈储存每一个多项式,最后根据导数的加法原则依次求导相加,注意取模。 C++代码 #pragma GCC optimize(3, "Ofast", "inline") #include <bits/stdc++.h> #define int long longusing namespace std; co…

OOP实验三

任务1: 源码:1 #pragma once2 3 #include <iostream>4 #include <string>5 6 using std::string;7 using std::cout;8 9 // 按钮类 10 class Button { 11 public: 12 Button(const string &text); 13 string get_label() const; 14 void click()…

鸿蒙NEXT开发案例:转盘1W

【1】引言(完整代码在最后面) 在鸿蒙NEXT系统中,开发一个有趣且实用的转盘应用不仅可以提升用户体验,还能展示鸿蒙系统的强大功能。本文将详细介绍如何使用鸿蒙NEXT系统开发一个转盘应用,涵盖从组件定义到用户交互的完整过程。 【2】环境准备 电脑系统:windows 10 开发工…

开源 - Ideal库 - 常用时间转换扩展方法(二)Qv

合集 - Ideal库 - Common库(2)1.开源 - Ideal库 - 常用时间转换扩展方法(一)11-07:悠兔机场2.开源 - Ideal库 - 常用时间转换扩展方法(二)11-09收起 书接上回,我们继续来分享一些关于时间转换的常用扩展方法。01、时间转日期时间 TimeOnly 该方式是把TimeOnly类型转为Date…

存储器的知识

以W25Q256为例子(外部Flash),结构如下:扇区的内部结构以F10系列为例子 64位代表的是8个字节的数据,一个地址最多可以存储8个字节的数据(double数据类型就是8个字节),4k,16k,64k,32k代表的是地址的总数,主存储块又可以分为很多个页,页里面也有存储的空间大小嵌入式闪存的组成

什么是git,什么是github,git和github的使用

Git实战注意:本项目是学习笔记,来自于哔哩哔哩武沛齐老师的Git实战视频, 网址:【武沛齐老师讲git,看完绝对上瘾!!!】 https://www.bilibili.com/video/BV1ne4y1E7np/?share_source=copy_web&vd_source=2c9a5d5590d3759367594e264ff079c4另外,因为这个博客是我直接…

law Intermediate walkthrough pg

靶场很简单分数只有10分跟平常做的20分的中级靶场比确实简单 我拿来放松的 算下来30分钟解决战斗 nmap 扫到80端口web界面 是个框架 搜exp https://www.exploit-db.com/exploits/52023 他的脚本可能有点问题看不到回显 我们审脚本直接看到漏洞点所在 命令执行 curl -s -d "…

streamlit run执行报错,Invalid value: File does not exist: XXX.py

streamlit run执行报错,Invalid value: File does not exist: XXX.py 在终端执行 streamlit run xxx.py 的时候报错提示 Invalid value: File does not exist: XXX.py 网上众说纷纭,但是我个人的解决方法其实非常简单 在终端中执行的时候会发现中间多了个warning翻译过来就是…

03_muduo_base3

5.6 互斥锁和条件变量的封装 类图该类是封装了互斥锁的一些基本操作,包括互斥锁的初始化、销毁、上锁、解锁等功能。但是实际上使用RAII技术又封装了一个类,那就是MutexLockGuard。这主要也是采取了类似智能指针的封装思路,让互斥锁的生命周期交给操作系统去管理,释放的时机…

B样条(BSpline,即 Basis Spline)

B 样条(BSpline)是一种在计算机图形学、计算机辅助设计、数值分析等领域广泛应用的数学曲线和曲面表示方法。以下是对 B 样条的详细定义: 一、基本概念 B 样条是基于一系列控制点(Control Points)来定义曲线或曲面的。它通过一个特定的基函数(Basis Functions)集合与这些…

实验3 类和对象

实验任务1: button.hpp#pragma once#include <iostream> #include <string>using std::string; using std::cout;// 按钮类 class Button { public:Button(const string &text);string get_label() const;void click();private:string label; };Button::Butto…

【LaTex 2024软件下载与安装教程】

1、安装包 Latex2024: 链接:https://pan.quark.cn/s/1dad34ca4d8f 提取码:5bja 2、安装教程 1) 双击压缩包内intall-tl-windows.bat安装,弹窗安装对话框2) 自动弹出安装窗口,如果弹出以下窗口说明文件夹目录太长或者有中文,建议放磁盘根目录;如果没有弹出…