当前位置: 首页 > news >正文

题解:AT_arc181_e [ARC181E] Min and Max at the edge

怎么给提高组小登会从绿题放到这种题,我们 [] 真是蒸蒸日上。

太厉害的题了,完全想不到。

题意:很简单了,不再赘述。

做法:

先不管删边的事情,我们先思考如何对一个图构造一棵树出来。

感觉对于这个 \((u,v)\) 的限制很有一种最小生成树的感觉,但是因为是对点的限制不对边所以完全没法做,但是我们考虑可以对边适当的赋权。那么为了表示点的限制,我们不妨把编号也映射到一个 \(A\) 数组上,同时保持了他们的偏序关系。我们会根据接下来的分析具体地给出我们对 \(A\) 数组的要求和一种简单的构造。

然后我们考虑把限制转到边上,我们希望 \(\forall k\in path(u,v),A_u\le A_k\le A_v\),那么把限制转到边上,假设中间有一条边 \((x,y)\),那么就是 \(A_u\le A_x,A_y\le A_v\),那么我们就要 \(w(x,y)< w(u,v)\)\(w\) 是这条边的权,我们直接取 \(A = x^i,w(u,v) = |A_u-A_v|\),这样去对整个图重新进行标权,跑出来的最小生成树就是唯一且合法的构造。

但是我们在实际写的时候肯定不能这么写,我们没法对这么大的数去做,但是我们注意到,只要满足对于 \(u\le x< y\le v\) 都有 \(w(u,v)>w(x,y)\) 那么就可以了,所以我们考虑令 \(w(u,v)=(n+1)v-u\),这样跑出来一个生成树就可以保证我路径上最大值一定是 \(v\),如果大一权都会大很多。

但是随之而来有一个问题,这样跑出来的 \(u\) 不一定是最小的,因为我可能连续的小 \(v\) 连在一起这样边权小一点,所以我们需要检验 \(u\) 也就是最小值的限制。我们只需要把边权改成 \(w(u,v)=(n+1-u)(n+1)-(n+1-v)\) 再跑一遍就可以了。最后判定是否可以找到一个树就直接看两个树跑出来的边集是否相同就可以了。

判断边集可以用 +/xor hash,但是还有删边的问题。其实也不难,就是我们考虑先跑出来一个生成树,如果不是树边,就直接用现在的就可以了;否则删掉之后找一条最小的去连通即可。这个东西可以是拍成 dfn 序然后变成平面问题或者用并查集合并边也可以。

代码:

别问我为什么我两种做法都写了,问题就是我 dfn 调不出来所以换成并查集,然后突然反应过来我 inf 开小了。

dfn 序:

#include <bits/stdc++.h>
using namespace std;
#define int long long
const int maxn = 5e5 + 5;
mt19937 rnd(time(0));
struct Edge {int u, v, w, val, id;friend bool operator<(Edge x, Edge y) {return x.w < y.w;}
} e[maxn];
vector<int> g[maxn];
int n, m, use[maxn], ans[2][maxn];
struct dsu {int pre[maxn];void init() {for (int i = 1; i <= n; i++)pre[i] = i;}int fnd(int x) {return (pre[x] == x ? x : pre[x] = fnd(pre[x]));}
} tree1;
struct node {int mn, val;friend node operator+(node x, node y) {return (x.mn < y.mn ? x : y);}
} ;
struct Segtree {node tr[maxn << 2];void pushup(int t) {tr[t] = tr[t << 1] + tr[t << 1 | 1];}void build(int l, int r, int t) {if(l == r) {tr[t] = {(int)9e18, 0};return ;}int mid = l + r >> 1;build(l, mid, t << 1), build(mid + 1, r, t << 1 | 1);pushup(t);}void modify(int l, int r, int pos, int t, node val) {if(l == r) {tr[t] = tr[t] + val;return ;}int mid = l + r >> 1;if(pos <= mid)modify(l, mid, pos, t << 1, val);elsemodify(mid + 1, r, pos, t << 1 | 1, val);pushup(t);}node query(int l, int r, int x, int y, int t) {if(x <= l && r <= y)return tr[t];int mid = l + r >> 1;if(y <= mid)return query(l, mid, x, y, t << 1);if(mid < x)return query(mid + 1, r, x, y, t << 1 | 1);return query(l, mid, x, y, t << 1) + query(mid + 1, r, x, y, t << 1 | 1);}
} tree;
int sz[maxn], dfn[maxn], tot, f[maxn];
node val[maxn];
void dfs(int u, int fa) {sz[u] = 1; dfn[u] = ++tot;f[u] = fa;for (int i = 0; i < g[u].size(); i++) {int v = g[u][i];if(v == fa)continue;dfs(v, u);sz[u] += sz[v];}
}
struct Value {int x, y, w, val;friend bool operator<(Value x, Value y) {return x.y < y.y;}
} ;
vector<Value> vec;
int pos[maxn];
vector<int> qry[maxn];
void kruskal(int k) {for (int i = 1; i <= m; i++)use[i] = 0;sort(e + 1, e + m + 1);for (int i = 1; i <= n; i++)g[i].clear();tree1.init();int res = 0;int cntt = 0;for (int i = 1; i <= m; i++) {int x = tree1.fnd(e[i].u), y = tree1.fnd(e[i].v);if(x == y)continue;use[i] = 1, res ^= e[i].val;tree1.pre[x] = y;g[e[i].u].push_back(e[i].v);g[e[i].v].push_back(e[i].u);cntt++;}if(cntt != n - 1)exit(1);tot = 0;dfs(1, 0);vec.clear();for (int i = 1; i <= m; i++) {if(use[i])continue;vec.push_back(Value{dfn[e[i].u], dfn[e[i].v], e[i].w, e[i].val});vec.push_back(Value{dfn[e[i].v], dfn[e[i].u], e[i].w, e[i].val});}sort(vec.begin(), vec.end());for (int i = 1; i <= n; i++)qry[i].clear();for (int i = 1; i <= m; i++) {if(use[i]) {if(f[e[i].v] == e[i].u)swap(e[i].u, e[i].v);qry[dfn[e[i].u] - 1].push_back(i);//	cout << dfn[e[i].u] << " " << e[i].u << " " << e[i].v << " " << e[i].id << endl;}}int cur = 0;tree.build(1, n, 1);for (int i = 1; i <= m; i++)val[i] = node{(int)9e18, 0};for (int i = 1; i <= n; i++) {//	cout << i << " adf" << endl;while(cur < vec.size() && vec[cur].y == i)tree.modify(1, n, vec[cur].x, 1, node{vec[cur].w, vec[cur].val}), cur++;for (int j = 0; j < qry[i].size(); j++)val[qry[i][j]] = val[qry[i][j]] + tree.query(1, n, dfn[e[qry[i][j]].u], dfn[e[qry[i][j]].u] + sz[e[qry[i][j]].u] - 1, 1);}tree.build(1, n, 1);cur--;for (int i = 1; i <= n; i++)qry[i].clear();for (int i = 1; i <= m; i++) {if(use[i]) qry[dfn[e[i].u] + sz[e[i].u]].push_back(i);}for (int i = n; i >= 1; i--) {while(cur >= 0 && vec[cur].y == i)tree.modify(1, n, vec[cur].x, 1, node{vec[cur].w, vec[cur].val}), cur--;for (int j = 0; j < qry[i].size(); j++)val[qry[i][j]] = val[qry[i][j]] + tree.query(1, n, dfn[e[qry[i][j]].u], dfn[e[qry[i][j]].u] + sz[e[qry[i][j]].u] - 1, 1);}for (int i = 1; i <= m; i++) {if(val[i].val || !use[i])ans[k][e[i].id] = (!use[i] ? res : (res ^ e[i].val ^ val[i].val));}
}
signed main() {
//	freopen("test.in", "r", stdin);
//	freopen("baoli.out", "w", stdout);cin >> n >> m;for (int i = 1; i <= m; i++)cin >> e[i].u >> e[i].v, e[i].val = rnd(), e[i].id = i;for (int i = 1; i <= m; i++)e[i].w = e[i].v * (n + 1) - e[i].u;kruskal(0);for (int i = 1; i <= m; i++) {if(e[i].u > e[i].v)swap(e[i].u, e[i].v);e[i].w = (n + 1 - e[i].u) * (n + 1) - (n + 1 - e[i].v);}kruskal(1);for (int i = 1; i <= m; i++)cout << (ans[1][i] == ans[0][i] && ans[1][i] && ans[0][i] ? "Yes" : "No") << endl;return 0;
}

并查集:

#include <bits/stdc++.h>
using namespace std;
#define int long long
const int maxn = 5e5 + 5;
mt19937 rnd(time(0));
struct Edge {int u, v, w, val, id;friend bool operator<(Edge x, Edge y) {return x.w < y.w;}
} e[maxn];
vector<int> g[maxn];
int n, m, use[maxn], ans[2][maxn];
struct dsu {int pre[maxn];void init() {for (int i = 1; i <= n; i++)pre[i] = i;}int fnd(int x) {return (pre[x] == x ? x : pre[x] = fnd(pre[x]));}
} tree1;
struct node {int mn, val;friend node operator+(node x, node y) {return (x.mn < y.mn ? x : y);}
} ;
int sz[maxn], dfn[maxn], tot, f[maxn], dep[maxn];
node val[maxn];
void dfs(int u, int fa) {sz[u] = 1; dfn[u] = ++tot;dep[u] = dep[fa] + 1;f[u] = fa;for (int i = 0; i < g[u].size(); i++) {int v = g[u][i];if(v == fa)continue;dfs(v, u);sz[u] += sz[v];}
}
struct Value {int x, y, w, val;friend bool operator<(Value x, Value y) {return x.y < y.y;}
} ;
vector<Value> vec;
int pos[maxn], id[maxn];
vector<int> qry[maxn];
void kruskal(int k) {for (int i = 1; i <= m; i++)use[i] = 0;sort(e + 1, e + m + 1);for (int i = 1; i <= n; i++)g[i].clear();tree1.init();int res = 0;int cntt = 0;for (int i = 1; i <= m; i++) {int x = tree1.fnd(e[i].u), y = tree1.fnd(e[i].v);if(x == y)continue;use[i] = 1, res ^= e[i].val;tree1.pre[x] = y;g[e[i].u].push_back(e[i].v);g[e[i].v].push_back(e[i].u);cntt++;}if(cntt != n - 1)exit(1);tot = 0;dfs(1, 0);for (int i = 1; i <= m; i++) {if(use[i]) {if(f[e[i].u] == e[i].v)swap(e[i].u, e[i].v);id[e[i].v] = i;}}vec.clear();tree1.init();for (int i = 1; i <= m; i++) {if(use[i])continue;int x = tree1.fnd(e[i].u), y = tree1.fnd(e[i].v);ans[k][e[i].id] = res;while(x != y) {if(dep[tree1.fnd(f[x])] < dep[tree1.fnd(f[y])])swap(x, y);ans[k][e[id[x]].id] = res ^ e[id[x]].val ^ e[i].val;//	cout << e[id[x]].id << "adsfdf " << x << " " << id[x] << endl;tree1.pre[x] = tree1.fnd(f[x]);x = tree1.fnd(x);}}
}
signed main() {
//	freopen("test.in", "r", stdin);
//	freopen("baoli.out", "w", stdout);cin >> n >> m;for (int i = 1; i <= m; i++)cin >> e[i].u >> e[i].v, e[i].val = rnd(), e[i].id = i;for (int i = 1; i <= m; i++)e[i].w = e[i].v * (n + 1) - e[i].u;kruskal(0);for (int i = 1; i <= m; i++) {if(e[i].u > e[i].v)swap(e[i].u, e[i].v);e[i].w = (n + 1 - e[i].u) * (n + 1) - (n + 1 - e[i].v);}kruskal(1);for (int i = 1; i <= m; i++)cout << (ans[1][i] == ans[0][i] && ans[1][i] && ans[0][i] ? "Yes" : "No") << endl;return 0;
}
http://www.hskmm.com/?act=detail&tid=25101

相关文章:

  • 酵母单杂交实验:解密 “转录因子 - DNA 互作” 的核心工具
  • api调用钉钉群机器人发信息 - 规格严格
  • 2025 年氢氧化铝生产厂家 TOP 品牌榜单来袭,阻燃,高白,酸融,导热,超细,微粉级,低粘度,灌封胶用,覆铜板用氢氧化铝公司推荐!
  • 飞算 JavaAI 赋能老工程重构:破旧立新的高效利器
  • P14139 题解
  • AI 自我理解边界
  • 2025钢球厂家最新企业品牌推荐排行榜,轴承钢球,不锈钢球,碳钢球,精密钢球,440C不锈钢球推荐这十家公司!
  • 2025 年工业提升门厂家最新企业品牌推荐排行榜,汇峰节能科技彰显行业影响力!
  • 什么是偏微分方程?
  • 2025 权威推荐!电梯源头品牌 TOP5 排行榜:实力厂家精选,品质之选不容错过
  • 钉钉红包性能优化之路 - 实践
  • IIS反向代理tomcat
  • 2025混合机厂家最新企业品牌推荐排行榜,高效盘条式混合机,无重力混合机,犁刀式混合机,锥形混合机,卧式螺带混合机推荐这十家公司!
  • 2025离心泵厂家最新企业品牌推荐排行榜! 卧式离心泵,化工离心泵,多级离心泵,卧式多级离心泵,不锈钢离心泵推荐这十家公司!
  • 2025真空炉厂家最新企业品牌推荐排行榜,高温烧结真空炉,真空退火炉,智能铍铜真空炉推荐这十家公司!
  • 【论文阅读】Dolphin: Document Image Parsing via Heterogeneous Anchor Prompting - 实践
  • 2025 --【J+S 二十连测】-- 第二套 总结
  • 2025 蒸发器厂家最新企业品牌推荐排行榜,江苏纵横携手知名品牌,彰显蒸发器公司行业影响力
  • 题解:Luogu P11976 [KTSC 2021] 通信网络 / communication
  • 弦振动方程
  • 理论构建尝试整理
  • 2025聚合硫酸铁厂家最新企业品牌推荐排行榜,工业聚合硫酸铁,混凝剂聚合硫酸铁,固态聚合硫酸铁,粉末聚合硫酸铁,硫酸亚铁公司推荐!
  • 2025成型机厂家最新企业品牌推荐排行榜,冷弯成型机,卷帘门成型机,卷闸门成型机,彩钢瓦成型机,货架成型机推荐!
  • 2025 年 PP 管厂家最新推荐榜:甄选 pp 风管,PP 喷淋塔,pp 洗涤塔,pp 通风管道优质公司!
  • 解密并下载受DRM保护的MPD(DASH流媒体)加密视频 - 教程
  • 在PyCharm中运行 wandb.login();
  • 机器学习科学家分享技术写作艺术
  • AT VP 记录
  • rpm安装
  • 关于主体性介枚枚介的讨究