20250222

T1

缆车

有向图中从 \(1\) 可达所有点等价于除 \(1\) 以外所有点都有入度。离散化之后容易求出每个左端点对应的最大合法右端点,求出这些区间之后对于一个询问,要么两边都扩展,要么只扩展一边。几种情况分别线段树维护即可。

代码
#include <iostream>
#include <algorithm>
#include <string.h>
#include <time.h>
#include <set>
#define lowbit(x) ((x) & (-(x)))
#define int long long
using namespace std;
#define getchar() p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++;
char buf[1<<21],*p1,*p2,ch;
long long read(){long long ret=0;char c=getchar();while(c<'0'||c>'9')c=getchar();while(c>='0'&&c<='9')ret=ret*10+c-'0',c=getchar();return ret;
}
const int inf = 0x3f3f3f3f3f3f3f3f;
inline void Cmin(int &x, int y) { x = min(x, y); }
int n, m, q, P;
multiset<int> st;
struct Edge {int u, v, w;
} e[300005];
int cur[300005];
int X[400005];
int d[1200005], dcnt;
inline int mp(int x) { return lower_bound(d + 1, d + dcnt + 1, x) - d; }
int R[1200005];
struct qquery {int l, r, id;
} qs[1200005];
int qcnt;
struct PBIT {int bit[1200005];void add(int x, int y) { for (; x <= 1200000; x += lowbit(x)) Cmin(bit[x], y); }int query(int x) {int ret = inf;for (; x; x -= lowbit(x)) Cmin(ret, bit[x]);return ret;}void clear() { memset(bit, 63, sizeof bit); }
} bit2, bit3;
struct SBIT {int bit[1200005];void add(int x, int y) { for (; x; x -= lowbit(x)) Cmin(bit[x], y); }int query(int x) {int ret = inf;for (; x <= 1200000; x += lowbit(x)) Cmin(ret, bit[x]);return ret;}void clear() { memset(bit, 63, sizeof bit); }
} bit0, bit1;
int ans[400005];
int ql[400005], qr[400005];
signed main() {int ttt = clock();freopen("car.in", "r", stdin);freopen("car.out", "w", stdout);bit0.clear(), bit1.clear();bit2.clear(), bit3.clear();n = read(), m = read(), P = read();for (int i = 1; i <= m; i++) e[i].u = read(), e[i].v = read(), e[i].w = d[++dcnt] = read();q = read();for (int i = 1; i <= q; i++) {int l = read(), r = read(); X[i] = read();d[++dcnt] = l, d[++dcnt] = r;ql[i] = l, qr[i] = r;}d[++dcnt] = inf;sort(d + 1, d + dcnt + 1);dcnt = unique(d + 1, d + dcnt + 1) - d - 1;for (int i = 2; i <= n; i++) st.insert(cur[i] = inf);sort(e + 1, e + m + 1, [](Edge a, Edge b) { return a.w < b.w; });for (int i = m; i; i--) {int x = e[i].v;st.erase(st.find(cur[x]));cur[x] = e[i].w;st.insert(cur[x]);R[mp(e[i].w)] = mp(*st.rbegin());}for (int i = 1; i <= m; i++) qs[++qcnt] = (qquery) { mp(e[i].w), R[mp(e[i].w)], -1 };for (int i = 1; i <= q; i++) qs[++qcnt] = (qquery) { mp(ql[i]), mp(qr[i]), i };sort(qs + 1, qs + qcnt + 1, [](qquery a, qquery b) { return a.l == b.l ? (a.id < b.id) : (a.l < b.l); });memset(ans, 63, sizeof ans);for (int i = 1; i <= qcnt; i++) {if (qs[i].id > 0) {Cmin(ans[qs[i].id], bit1.query(qs[i].r) + d[qs[i].l] - d[qs[i].r]);Cmin(ans[qs[i].id], bit2.query(qs[i].r) + d[qs[i].l]);} else {bit1.add(qs[i].r, d[qs[i].r] - d[qs[i].l]);bit2.add(qs[i].r, -d[qs[i].l]);}}sort(qs + 1, qs + qcnt + 1, [](qquery a, qquery b) { return a.l == b.l ? (a.id < b.id) : (a.l > b.l); });for (int i = 1; i <= qcnt; i++) {if (qs[i].id > 0) {Cmin(ans[qs[i].id], bit0.query(qs[i].r) - d[qs[i].r]);Cmin(ans[qs[i].id], bit3.query(qs[i].r));} else {bit0.add(qs[i].r, d[qs[i].r]);bit3.add(qs[i].r, 0);}}for (int i = 1; i <= q; i++) cout << (ans[i] <= X[i] ? "Yes\n" : "No\n");cerr << (1.0 * clock() - ttt) / CLOCKS_PER_SEC << "\n";return 0;
}

T2

容易发现当序列足够长时可以使用不超过 \(5\) 次操作将一个数移到它该在的位置上。具体地,如果这个数原来的位置不能走到它该在的位置,就先调整 \(x\) 的位置再用 \(x\) 跟它交换一次。然后调整 \(x\) 的位置,再把 \(x\) 换到这个数该在的位置,然后交换 \(x\) 和这个数。会发现只要剩余序列长度 \(\ge 4\) 且未排好的序列是连续的,则这个操作就可以做下去。因此每次选择未被排好序的最大值或最小值把它放好即可。最后剩余长度为 \(3\),先把 \(x\) 放到它该在的位置,然后剩下两个若是逆序则不合法,否则合法。因为操作不会改变逆序对数与 \(x\) 之和的奇偶性,所以做到最后如果剩一个逆序则一定不合法。

代码
#include <iostream>
#include <string.h>
#include <cassert>
#include <vector>
#include <array>
#define lowbit(x) ((x) & (-(x)))
#define int long long
using namespace std;
int n, X;
int p[300005], _p[300005];
vector<array<int, 2> > vec;
void op(int x, int y) {if (x != y) {swap(p[x], p[y]);swap(_p[p[x]], _p[p[y]]);vec.emplace_back((array<int, 2>) { x, y });}
}
struct BIT {int bit[300005];void add(int x, int y) { for (; x; x -= lowbit(x)) bit[x] += y; }int query(int x) {int ret = 0;for (; x <= 300000; x += lowbit(x)) ret += bit[x];return ret;}void clear() { memset(bit, 0, sizeof bit); }
} bit;
signed main() {freopen("big.in", "r", stdin);freopen("big.out", "w", stdout);int tc;cin >> tc;while (tc--) {bit.clear();vec.clear();cin >> n >> X;int cnt = 0;for (int i = 1; i <= n; i++) cin >> p[i], _p[p[i]] = i, cnt += bit.query(p[i]), bit.add(p[i], 1);int c = _p[X]; cnt += c;if ((cnt & 1) != (X & 1)) {cout << "NO\n";continue;}for (int i = 1, l = 1, r = n; i <= n - 3; i++) {int x, s;if (l != X) s = l, x = _p[l], ++l;else s = r, x = _p[r], --r;if (!((x ^ s) & 1)) {if ((c ^ x) & 1) op(c, x), swap(c, x);else {int t = 0;for (int k = r; k >= l; k--) {if (((k ^ c) & 1) && k != x && k != c) {t = k;break;}}op(c, t), c = t;op(c, x), swap(c, x);}}if (!((c ^ s) & 1)) {int t = 0;for (int k = r; k >= l; k--) {if (((k ^ c) & 1) && k != x && k != c) {t = k;break;}}op(c, t), c = t;}op(c, s), c = s;op(c, x), swap(c, x);}if (!((c ^ X) & 1)) {int t = 0;for (int k = n; k; k--) {if (((k ^ c) & 1) && k != c && p[k] != k) {t = k;break;}}op(c, t), c = t;}op(c, X);cout << "YES\n";cout << vec.size() << "\n";for (auto v : vec) cout << v[0] << " " << v[1] << "\n";}return 0;
}

T3

邮局

朴素的贪心是如果一个点有多个包裹,先送走目的地更远的。但是这没法维护,我们考虑对每条边算贡献。我们考虑一条边最后被经过的时间,然后把所有边取 \(\max\)。接下来只考虑一条边的贡献。设经过这条边的包裹到这条边起点的距离为 \(d_{1, 2, \cdots k}\)(按离开顺序排列),则每个包裹离开这条边的时间 \(t_i = \max\{t_{i - 1}, d_i\} + 1\),也就是 \(t_k = \max\{ d_i + k - t + 1 \}\)。若要最小化这个式子,显然应该视 \(d\) 为升序,此时每个包裹的贡献即为其距离加上距离 \(\ge\) 它的包裹个数。只需要维护这个即可。在树上可以直接线段树合并,基环树上可以破环为链,此时只需要保证每条边被覆盖的集合正确。把链拼一份到后面,则顺序只需要 \(s \rightarrow t\),逆序拆成就 \(s + n \rightarrow t, s \rightarrow 1\) 即可。

代码
#include <iostream>
#include <vector>
using namespace std;
#define getchar() p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1 << 21, stdin), p1 == p2) ? EOF : *p1++
char buf[1<<21], *p1, *p2, ch;
long long read() {long long ret = 0, neg = 0; char c = getchar(); neg = (c == '-');while (c < '0' || c > '9') c = getchar(), neg |= (c == '-');while (c >= '0' && c <= '9') ret = ret * 10 + c - '0', c = getchar();return ret * (neg ? -1 : 1);
}
int n, m, ans;
vector<int> G[400005];
int fa[400005];
int dsu[400005], dep[400005], top[400005], dfn[400005], *L = dfn, R[400005];
int op[400005], rt[400005], ncnt;
vector<int> del[400005];
struct node {int mx, s, l, r;
} T[10000005];
struct Segment_Tree {int ncnt;void pushup(int o){T[o].s = T[T[o].l].s + T[T[o].r].s;T[o].mx = max(T[T[o].r].mx, T[T[o].l].mx + T[T[o].r].s);}void Add(int &o, int l, int r, int x, int y){if (!o) o = ++ncnt;if (l == r) return T[o].s += y, T[o].mx = (T[o].s ? l + T[o].s : 0), void();int mid = (l + r) >> 1;if (x <= mid) Add(T[o].l, l, mid, x, y);else Add(T[o].r, mid + 1, r, x, y);pushup(o);}int Merge(int p,int q,int l,int r){if (!p || !q) return p | q;if (l == r){T[p].s += T[q].s, T[p].mx = (T[p].s ? l + T[p].s : 0);return p;}int mid = (l + r) >> 1;T[p].l = Merge(T[p].l, T[q].l, l, mid);T[p].r = Merge(T[p].r, T[q].r, mid + 1, r);pushup(p);return p;}
}seg;
int getf(int x) { return (dsu[x] == x ? x : (dsu[x] = getf(dsu[x]))); }
void dfs(int x){L[x] = ++ncnt;for (int v : G[x]) {dep[v] = dep[x] + 1;top[v] = (x ? top[x] : v);dfs(v);}R[x] = ncnt;
}
inline void add(int x, int y){del[x].emplace_back(y),++op[y];}
void dfs1(int x){for (int v : G[x]) dfs1(v), rt[x] = seg.Merge(rt[x], rt[v], 0, n << 1);seg.Add(rt[x], 0, n<<1, dep[x], op[x]);for (int v : del[x]) seg.Add(rt[x], 0, n << 1, dep[v], -1);ans = max(ans, T[rt[x]].mx - dep[x]);
}
int main() {freopen("postoffice.in", "r", stdin);freopen("postoffice.out", "w", stdout);n = read();for (int i = 1; i <= n; i++) dsu[i] = i;for (int i = 1; i <= n; i++) fa[i + n] = (fa[i] = read()) + n, dsu[getf(i)] = getf(fa[i]);for (int i = 1; i <= n; i++){if (getf(i) == i){int x = i;for(; dsu[x]; x = fa[x]) dsu[x]=0;fa[x + n] = fa[x], fa[x] = 0;}}for (int i = 1; i <= n * 2; i++) G[fa[i]].emplace_back(i);dfs(0);m = read();for(int x, y, i = 1; i <= m; i++){x = read(), y = read();if (L[y] <= dfn[x] && dfn[x] <= R[y]) add(y,x);else if (L[y] <= dfn[x + n] && dfn[x + n] <= R[y]) add(y, x + n), add(top[y], x);else cout << "-1\n", exit(0);}dfs1(0);cout << ans << "\n";return 0;
}

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

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

相关文章

MyBatis-Plus 的自动填充 —— 值为null

MyBatis-Plus 的自动填充 MyBatis-Plus 提供的字段自动填充功能是一种非常实用的特性,它能够在插入或更新数据库记录时自动填充一些公共字段,如创建时间(createTime)、更新时间(updateTime)、创建人(createBy)、更新人(updateBy)等。这一功能极大地简化了开发过程,减…

[Jaav SE/程序生命周期] 优雅的Java应用程序的启停钩子框架

序了解 spring 生态及框架的 java er 都知道,spring 应用的生命周期管理及配套接口较为优雅、可扩展。但脱离 spring 的 java 应用程序,如何优雅地启停、管理程序的生命周期呢?(以便应用程序在我们需要的运行阶段中进行相应的动作)概述:Java普通应用程序的启停钩子框架 前…

迈金C416码表体验

之前一直在用黑鸟单车和小米健康记录骑行数据, 后来又发现strava和keep的骑行分享功能做的比较好. 于是使用的运动app就越来越多, 骑行时带着手机的同时还要开好几个app太麻烦了, 同时也想给车上加一个速度显示器, 由此考虑入一个码表.对功能要求不高, 最主要的需求是gps和速度…

ASP.NET Core Swagger 汉化

在wwwroot文件夹添加汉化的JS文件const translations = {"Failed to load API definition": "API定义加载失败","Errors": "错误信息","Hide": "隐藏","Fetch error": "获取错误","Inte…

Svelte 最新中文文档教程(17)—— 生命周期钩子

前言 Svelte,一个语法简洁、入门容易,面向未来的前端框架。从 Svelte 诞生之初,就备受开发者的喜爱,根据统计,从 2019 年到 2024 年,连续 6 年一直是开发者最感兴趣的前端框架 No.1:Svelte 以其独特的编译时优化机制著称,具有轻量级、高性能、易上手等特性,非常适合构…

[Java SE] FunctionInterface 注解: 函数式接口(JDK8+)

概述:FunctionInterface/函数式接口 简介函数式接口是指只包含一个抽象方法的接口,可以使用 Lambda 表达式来创建该接口的实例。@FunctionalInterface 注解是 Java Lang 包中的一个注解,用于标识一个接口是函数式接口。@FunctionalInterface 注解的作用:编译时检查:@Funct…

去中心化 AI:赋权还是混乱?

DeepSeek 如何在 AI 去中心化方面迈出了巨大的一步,以及为什么这比你想象的更重要Nadia Piet + AIxDESIGN & Archival Images of AI / Better Images of AI / AI Am Over It / CC-BY 4.02025 年 1 月 27 日星期一,DeepSeek —— 一家几乎凭空冒出来的中国初创公司 —— 发…

SmolLM2:多阶段训练策略优化和高质量数据集,小型语言模型同样可以实现卓越的性能表现

SmolLM2 采用创新的四阶段训练策略,在仅使用 1.7B 参数的情况下,成功挑战了大型语言模型的性能边界:在 MMLU-Pro 等测试中超越 Qwen2.5-1.5B 近 6 个百分点 数学推理能力(GSM8K、MATH)优于 Llama3.2-1B 在代码生成和文本重写任务中展现出色表现 支持 8K tokens 的长文本处…

2025.2.23 (java的学习)

。。。昨天星期六一整天都没学习。。做了一个哆啦a梦。✌附一个目前弄的哆啦a梦全家桶吧。

自动驾驶两个传感器之间的坐标系转换

有两种方式可以实现两个坐标系的转换。 车身坐标系下一个点p_car,需要转换到相机坐标系下,旋转矩阵R_car2Cam,平移矩阵T_car2Cam。点p_car在相机坐标系下记p_cam. 方法1:先旋转再平移 p_cam = T_car2Cam * p_car + T_car2Cam 需要注意的是,这里的平移矩阵T_car2Cam是车身坐…

8-2 MySQL 索引的设计原则(超详细说明讲解)

8-2 MySQL 索引的设计原则(超详细说明讲解) @目录8-2 MySQL 索引的设计原则(超详细说明讲解)1. 测试数据准备2. 哪些情况适合创建索引2.1 字段的数值有唯一性的限制2.2 频繁作为 WHERE 查询条件的字段2.3 经常 GROUP BY 和 ORDER BY 的列2.4 UPDATE、DELETE 的 中的WHERE 条件列…

北京时间同步

本地时间与北京时间 同步 参考:https://blog.csdn.net/qq_46092061/article/details/128748789 本地显示秒数while True:current_time = time.strftime("%H:%M:%S")if current_time >= "19:59:59":print("start")breaktime.sleep(0.5) # 减…