首页 > 其他分享 >CF464E 解题报告

CF464E 解题报告

时间:2024-02-26 23:26:03浏览次数:26  
标签:return 报告 int CF464E tr mid 解题 sum flg

首先这是一道最短路的题目,但是数据范围十分庞大,需要高精度。但是数据范围实在太庞大了,高精度的时间复杂度是很高的,所以我们另辟蹊径。

考虑到每条边边权都是 \(2^x\) 的形式,提示我们将起点到每个点的最短距离转化为二进制形式。考虑松弛操作需要用到什么,发现需要比较两个二进制数的大小,以及两个二进制数的相加。

对于比大小,我们只需要用 hash 找到两个二进制数的最长公共前缀,比较最长公共前缀的下一位就行。

对于相加,我们发现其中一个加数是 \(2^x\) 的形式,意味着会有一段连续的 \(1\) 变成 \(0\),再将一个 \(0\) 变成 \(1\)(自己手动模拟一下会发现)。这个操作只需要先二分出端点,再用线段树操作即可。

??线段树?有 \(n\) 个点,每个点如果都维护一个最长为 \(10^5\) 位的二进制数,显然是存不下的。所以我们用可持久化线段树来维护,以 \(root_i\) 为根的线段树代表起点到 \(i\) 的最短距离的二进制形式。主席树内需要维护当前区间 hash 值,和最短距离 sum。

1.64s / 395.52MB / 3.61KB / C++14 (GCC 9)

#include <bits/stdc++.h>
using namespace std;

const int N = 2e5 + 5, mod = 1e9 + 7;

int n, m, S, T, pw2[N], b[N], root[N], idx;
vector<pair<int, int> > G[N];

struct edge {
	int l, r;
	int sum, flg, has;
}tr[N * 100];

void push_up(int p) {
	tr[p].sum = (tr[tr[p].l].sum + tr[tr[p].r].sum) % mod; // sum为最短距离
	tr[p].flg = tr[tr[p].l].flg & tr[tr[p].r].flg; // flg表示这个区间是否全部为1,用于来找连续的1
	tr[p].has = (tr[tr[p].l].has % mod + tr[tr[p].r].has) % mod; // hash
}

int build(int l, int r, int v) {
	int p = ++idx;
	if (l == r) {
		tr[p].sum = pw2[l] * v % mod;
		tr[p].flg = v, tr[p].has = b[l] * v % mod;
		return p;
	}
	int mid = (l + r) >> 1;
	tr[p].l = build(l, mid, v);
	tr[p].r = build(mid + 1, r, v);
	push_up(p);
	return p;
}

int query_flg(int p, int l, int r, int L, int R) { // [L,R] 区间是否全部为1
	if (L <= l && r <= R) return tr[p].flg;
	int res = 1, mid = (l + r) >> 1;
	if (L <= mid) res &= query_flg(tr[p].l, l, mid, L, R);
	if (R > mid) res &= query_flg(tr[p].r, mid + 1, r, L, R);
	return res;
}

int clear(int now, int l, int r, int L, int R) { // 将 [L,R] 置 0
	int p = ++idx;
	tr[p] = tr[now];
	if (L <= l && r <= R) {
		tr[p] = {0, 0, 0, 0, 0}; // 我们可以直接将子树都丢掉,不用标记永久花
		return 0;
	}
	int mid = (l + r) >> 1;
	if (L <= mid) tr[p].l = clear(tr[now].l, l, mid, L, R);
	if (R > mid) tr[p].r = clear(tr[now].r, mid + 1, r, L, R);
	push_up(p);
	return p;
}

int modify(int now, int l, int r, int x) { // x 位变为1
	int p = ++idx;
	tr[p] = tr[now];
	if (l == r) {
		tr[p].sum = pw2[l];
		tr[p].has = b[l], tr[p].flg = 1;
		return p;
	}
	int mid = (l + r) >> 1;
	if (x <= mid) tr[p].l = modify(tr[now].l, l, mid, x);
	else tr[p].r = modify(tr[now].r, mid + 1, r, x);
	push_up(p);
	return p;
}

void addone(int rt, int x) { // 加上2^x的结果,存到root[n+1]的线段树内
	int l = x, r = N - 5;
	while (l < r) {
		int mid = (l + r + 1) >> 1;
		if (query_flg(root[rt], 0, N - 5, x, mid)) l = mid;
		else r = mid - 1;
	}
	root[n + 1] = root[rt];
	if (x <= l && query_flg(root[rt], 0, N - 5, x, l)) {
		root[n + 1] = clear(root[n + 1], 0, N - 5, x, l);
		root[n + 1] = modify(root[n + 1], 0, N - 5, l + 1);	
	}
	else {
		root[n + 1] = modify(root[n + 1], 0, N - 5, l);	
	}
//	cout << "ww=" << query_flg(root[n + 1], 0, N - 5, x - 1, x) << endl;
}

int cmp(int a, int b, int l, int r) { // 比较大小
	if (l == r) return tr[a].flg > tr[b].flg;
	int mid = (l + r) >> 1;
	if (tr[tr[a].r].has != tr[tr[b].r].has) return cmp(tr[a].r, tr[b].r, mid + 1, r);
	return cmp(tr[a].l, tr[b].l, l, mid);
}

struct node {
	int u, rt;
	friend bool operator < (node a, node b) {
		return cmp(a.rt, b.rt, 0, N - 5);
	}
};
priority_queue<node> q;
int st[N], pre[N];

void dij() {
	root[S] = build(0, N - 5, 0);
	root[0] = build(0, N - 5, 1);
	for (int i = 1; i <= n; i++) {
		if (i != S) root[i] = root[0];
	}
	q.push({S, root[S]});
	while (q.size()) {
		auto t = q.top(); q.pop();
		int u = t.u;
		if (st[u]) continue;
		st[u] = 1;
		for (auto e : G[u]) {
			int v = e.first, w = e.second;
			addone(u, w);
			if (cmp(root[v], root[n + 1], 0, N - 5)) {
				root[v] = root[n + 1];
				pre[v] = u;
				q.push({v, root[v]});
			}
		}
	}
}

vector<int> ans;

signed main() {
	cin >> n >> m;
	for (int i = 1; i <= m; i++) {
		int u, v, w;
		cin >> u >> v >> w;
		G[u].push_back({v, w});
		G[v].push_back({u, w});
	}
	pw2[0] = b[0] = 1;
	for (int i = 1; i <= N - 4; i++) pw2[i] = pw2[i - 1] * 2 % mod, b[i] = b[i - 1] * 131 % mod;
	cin >> S >> T;
	dij();
	if (tr[root[T]].sum == pw2[N - 4] - 1) puts("-1"), exit(0);
	cout << tr[root[T]].sum << endl;
	int tmp = T;
	while (tmp != S) {
		ans.push_back(tmp);
		tmp = pre[tmp];
	}
	ans.push_back(S);
	cout << ans.size() << endl;
	reverse(ans.begin(), ans.end());
	for (auto v : ans) cout << v << ' ';
}

标签:return,报告,int,CF464E,tr,mid,解题,sum,flg
From: https://www.cnblogs.com/stOtue/p/18035819

相关文章

  • 【专题】2023年金融、保险、银行行业报告汇总PDF合集分享(附原数据表)
    原文链接:https://tecdat.cn/?p=35149原文出处:拓端数据部落公众号自中国提出双碳目标以来,可持续金融市场呈现出蓬勃发展的态势。这一发展趋势在多年来得到可持续金融战略咨询团队的支持和推动。同时,数字化转型的深入推进推动了新客户的增长,而中国的碳金融创新也成为市场关注的焦......
  • 2024 52pojie春节解题领红包之Windows 高级题
    202452pojie春节解题领红包之Windows高级题分析:crackme2024.exex64位程序upx脱壳,x64dbg设置异常,手动脱壳,略反调试cinit-->initterm_4定位到如下函数VEH_antiBP_140001670__int64VEH_antiBP_140001670(){qword_140020E58=findCC_1400022F0(0x64,0i64);AddVe......
  • Power BI - 如何对发布的报告进行分组
    故事背景:用户在PowerBI发布报告后,页导航中的报告一般是不分组的(如图红色矩形框内容).如何才能在页导航中,将报告进行分组(如图红色矩形框内容)?方便查看报告用户在前端看报告的时候会更有逻辑性,条理性。 解决方案:解决方案需要通过创建PowerBIAppreport来实现。 ......
  • 模拟赛 2024.2.16 解题报告
    A.楼房搭建题意:有\(n\)个数\(a_{1...n}\),以及初始全是\(0\)的\(b_{1...n}\)。现在每次选择一个\(i\in[1,n-1]\),然后选择下面一个操作:\(a_i\getsa_i+1,\spacea_{i+1}\getsa_{i+1}+2\)\(a_i\getsa_i+2,\spacea_{i+1}\getsa_{i+1}+1\)求使得\(\foralli,b......
  • pytest简易教程(34):pytest常用插件 - 测试报告(pytest-html)
     pytest简易教程汇总,详见:https://www.cnblogs.com/uncleyong/p/17982846关于pytest-html通过命令行方式,生成xml/html格式的测试报告,存储于用户指定路径报告会覆盖上一次的 插件安装pipinstallpytest-html 使用方式命令行格式:pytest--html=./report/report.html......
  • 袋鼠云产品功能更新报告09期|更全面,更多样,更高效
    欢迎阅读袋鼠云09期产品功能更新报告。在此期报告中,我们秉持创新与优化并重的理念,对产品进行了深度打磨与全面升级。每一处细节的改进,都是我们对卓越品质的不懈追求,期待这些新功能能助力您的业务运营与发展,让数字化转型之路更加畅通无阻。以下为袋鼠云产品功能更新报告09期内容,更......
  • 软件开发全套文档资料(规格说明书、详细设计、测试计划、验收报告)
    在软件全周期中,每个阶段都涉及不同的文档和支撑材料,以确保项目的顺利进行和最终的成功交付。以下是针对您列出的每个阶段所需的文档和支撑材料的简要概述。所有资料获取:https://www.cnblogs.com/suchen621/p/180254681.开发阶段需求文档:详细记录用户需求、业务需求和功能需求......
  • 【专题】2023年全球移动应用(非游戏)营销趋势白皮书报告PDF合集分享(附原数据表)
    原文链接:https://tecdat.cn/?p=35180原文出处:拓端数据部落公众号随着国内政策调整,移动APP业务前景充满不确定性,但这也为出海应用带来了新机遇。2023年,AI和短剧应用的崛起为出海行业注入了信心。随着用户需求增长和技术进步,这两个领域有望在2024年迎来更大发展。阅读原文,获取专......
  • 【专题】中国企业财务数字化转型白皮书报告PDF合集分享(附原数据表)
    报告链接:http://tecdat.cn/?p=32389原文出处:拓端数据部落公众号新冠疫情等对商业活动进行了重新塑造,并使金融活动在商业活动中的位置发生了变化。在可持续发展的时代背景下,财务人员需要适应新的工作模式,主动接受新的技术,将关注的重点从传统的财务报告范围拓展到可持续性、包容性......
  • monkey命令及性能报告结果分析
    monkey命令adbshellmonkey-pcom.mihoyo.hyperion-s 1708647041443 -v-v-v--throttle300--ignore-crashes--ignore-timeouts10>【文件路径】操作次数10写在命令最后。-p,指定包进行操作;-s,指定固定的seed值(伪随机数生成器的seed值。如果用相同的seed值再次运行m......