P2680 [NOIP2015 提高组] 运输计划 第一个测试点信息 || 被卡常,链式前向星应该解决的是vector的push_back频繁扩容的耗时

news2024/12/28 20:40:53

[NOIP2015 提高组] 运输计划 - 洛谷

目录

测试点信息

P2680_1.in

P2680_1.out

图:

50分参考代码(开了n^2的数组,MLE了):


测试点信息

Subtask #0

#1

P2680_1.in

100 1
7 97 4
89 2 0
40 91 1
70 84 1
36 92 3
28 20 0
25 100 1
76 56 2
58 47 3
87 76 0
57 51 4
6 36 0
71 47 0
13 50 3
83 98 5
19 36 1
75 26 3
50 86 2
81 78 1
70 41 5
44 4 2
21 90 1
18 65 4
51 93 3
22 38 0
10 89 3
28 83 3
72 29 3
62 81 0
25 35 0
5 71 2
17 62 1
88 68 0
10 11 3
4 80 2
56 99 4
27 94 2
53 54 4
67 37 4
40 52 5
23 30 4
64 70 5
52 85 4
22 92 4
13 91 0
90 32 1
61 65 2
81 34 0
75 43 0
8 5 4
38 1 1
12 45 2
68 31 4
97 95 4
38 94 5
81 48 5
12 61 5
60 97 0
39 41 3
46 99 1
32 52 5
55 11 2
29 11 3
71 85 4
55 77 3
72 70 4
8 51 5
8 24 2
64 95 5
79 84 5
30 63 0
27 35 1
73 69 4
83 75 2
87 33 0
98 9 1
66 31 0
3 33 2
30 16 3
87 80 1
4 48 0
16 55 0
73 32 5
14 17 5
29 36 4
76 37 5
96 9 3
81 31 2
8 9 2
16 49 1
83 15 0
68 54 2
18 58 1
61 84 3
83 42 3
26 82 3
42 53 0
25 59 1
21 74 0
96 81

P2680_1.out

19

图:

我发现之间有5这个长度,弄这个是因为我差分写错了没发现。。 

50分参考代码(开了n^2的数组,MLE了):

//所有飞船一起飞的啊,,,
//二分,分的是答案,超过的他们去减边,如果可以都比mid小,那么答案成立

struct edge
{
	int u, v;
	ll elen;
};
bool cmp(edge a,edge b)
{
	return a.elen < b.elen;
}

void solve()
{
	int n, m;
	cin >> n >> m;
	vector<vector<int>>alist(n + 1);
	vector<vector<int>>cost(n + 1,vector<int>(n+1));
	for (int i = 0; i < n - 1; i++)
	{
		int a, b, t;
		cin >> a >> b >> t;
		alist[a].push_back(b);
		alist[b].push_back(a);
		cost[a][b] = cost[b][a] = t;
	}
	vector<vector<int>>fa(n + 1, vector<int>(22));
	vector<int>dep(n + 1);
	vector<int>plen(n + 1);

	auto dfs = [&](int cur, int pa, auto dfs)->void {
		dep[cur] = dep[pa] + 1;
		plen[cur] += cost[cur][pa];
		for (auto x : alist[cur])
		{
			if (x != pa)
			{
				fa[x][0] = cur;
				plen[x] = plen[cur];
				dfs(x, cur, dfs);
			}
		}
	};
	dfs(1, 0, dfs);
	//倍增求父亲
	for (int p = 1; p < 22; p++)
	{
		for (int i = 1; i <= n; i++)
		{
			fa[i][p] = fa[fa[i][p - 1]][p - 1];
		}
	}
	
	auto LCA = [&](int a, int b)->pair<int, int>
	{
		ll ans = 0;
		if (dep[a] < dep[b])swap(a, b);

		while (dep[a] > dep[b])
		{
			int dis = (int)log2(dep[a] - dep[b]);
			a = fa[a][dis];
			ans += pow(2, dis);
		}

		for (int i = log2(dep[a]); i >= 0; i--)
		{
			if (fa[a][i] != fa[b][i])	//向上结果不同才跳
			{
				a = fa[a][i];
				b = fa[b][i];
				ans += pow(2, i) * 2;
			}
		}
		if (a != b)
		{
			a = b = fa[a][0];
			ans += 2;
		}
		return { a ,ans };
	};

	//两条边的距离就是到根节点,然后减去lca到根节点。

	vector<edge>channel(m);
	//vector<int>u(m),v(m);
	//vector<ll>elen(m);//所有边长数组
	for (int i = 0; i < m; i++)
	{
		cin >> channel[i].u >> channel[i].v;
		int u = channel[i].u, v = channel[i].v;
		channel[i].elen = (ll)plen[u] + plen[v] - (ll)plen[LCA(u, v).first]*2;
	}

	sort(channel.begin(), channel.end(),cmp);

	auto check = [&](int mid)->bool
	{
		int l = 0, r = m-1;
		while (l < r)
		{
			int m = l + (r - l) / 2;
			if (channel[m].elen > mid)r = m;
			else l = m+1;
		}
		// l ~ m-1 差分
		vector<int>arr(n + 1);
		for (int i = l; i < m; i++)
		{
			arr[channel[i].u]++;
			arr[channel[i].v]++;
			int f = LCA(channel[i].u, channel[i].v).first;
			arr[f] -= 2;
		}
		priority_queue<int, vector<int>, less<int>>aedge;
		auto dfs2 = [&](int cur, int pa, auto dfs2)->int
		{
			ll cn = arr[cur];
			for (auto x : alist[cur])
			{
				if (x != pa)
				{
					cn += dfs2(x, cur, dfs2);
				}
			}
			if (cn == m - l)
				aedge.push(cost[cur][pa]);
			return cn;//哇,差分啊当然返回总的啊
		};
		dfs2(1, 0, dfs2);
		//

		if (aedge.size() == 0)
			return false;
		if (channel[m - 1].elen - aedge.top() <= mid)
			return true;
		return false;
	};
	ll left = 0, right = channel[m - 1].elen;
	while (left<right)
	{
		ll mid = left + (right - left) / 2;
		if (check(mid))right = mid;
		else left = mid + 1;
	}
	cout << left;
}
signed main()
{
	ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
	int t = 1;
	//cin >> t;
	while (t--)
	{
		solve();
	}
	return 0;
}

95分邻接表被卡常:


inline int read()
{
	int x = 0, f = 1;
	char ch = getchar();
	while (ch < '0' || ch>'9')
	{
		if (ch == '-')
			f = -1;
		ch = getchar();
	}
	while (ch >= '0' && ch <= '9')
	{
		x = (x << 1) + (x << 3) + (ch ^ 48);
		ch = getchar();
	}
	return x * f;
}
inline void write(int x)
{
	if (x < 0)
	{
		putchar('-');
		x = -x;
	}
	if (x > 9)
		write(x / 10);
	putchar(x % 10 + '0');
}

struct edge
{
	int u, v;
	ll elen;
};
bool cmp(edge a,edge b)
{
	return a.elen < b.elen;
}

struct node
{
	int b, t;
};

void solve()
{
	int n, m;
	cin >> n >> m;
	vector<vector<node>>alist(n + 1);
	for (int i = 0; i < n - 1; i++)
	{
		int a, b, t;
		//cin >> a >> b >> t;
		a = read();
		b = read();
		t = read();
		alist[a].push_back({ b,t });
		alist[b].push_back({ a,t });
	}
	vector<vector<int>>fa(n + 1, vector<int>(22));
	vector<int>dep(n + 1);
	vector<int>plen(n + 1);

	auto dfs = [&](int cur, int pa, auto dfs)->void {
		dep[cur] = dep[pa] + 1;

		for (auto y : alist[cur])
		{
			int x = y.b;
			if (x != pa)
			{
				fa[x][0] = cur;
				plen[x] += y.t+plen[cur];
				dfs(x, cur, dfs);
			}
		}
	};
	dfs(1, 0, dfs);
	//倍增求父亲
	for (int p = 1; p < 22; p++)
	{
		for (int i = 1; i <= n; i++)
		{
			fa[i][p] = fa[fa[i][p - 1]][p - 1];
		}
	}
	
	auto LCA = [&](int a, int b)->pair<int, int>
	{
		ll ans = 0;
		if (dep[a] < dep[b])swap(a, b);

		while (dep[a] > dep[b])
		{
			int dis = (int)log2(dep[a] - dep[b]);
			a = fa[a][dis];
			ans += pow(2, dis);
		}

		for (int i = log2(dep[a]); i >= 0; i--)
		{
			if (fa[a][i] != fa[b][i])	//向上结果不同才跳
			{
				a = fa[a][i];
				b = fa[b][i];
				ans += pow(2, i) * 2;
			}
		}
		if (a != b)
		{
			a = b = fa[a][0];
			ans += 2;
		}
		return { a ,ans };
	};



	vector<edge>channel(m);
	for (int i = 0; i < m; i++)
	{
		//cin >> channel[i].u >> channel[i].v;
		channel[i].u = read();
		channel[i].v = read();
		int u = channel[i].u, v = channel[i].v;
		channel[i].elen = (ll)plen[u] + plen[v] - (ll)plen[LCA(u, v).first]*2;
	}

	sort(channel.begin(), channel.end(),cmp);

	auto check = [&](int mid)->bool
	{
		int l = 0, r = m-1;
		while (l < r)
		{
			int m = l + (r - l) / 2;
			if (channel[m].elen > mid)r = m;
			else l = m+1;
		}
		// l ~ m-1 差分
		vector<int>arr(n + 1);
		for (int i = l; i < m; i++)
		{
			arr[channel[i].u]++;
			arr[channel[i].v]++;
			int f = LCA(channel[i].u, channel[i].v).first;
			arr[f] -= 2;
		}
		//priority_queue<int, vector<int>, less<int>>aedge;
		ll maxo = -1;
		auto dfs2 = [&](int cur, int pa, auto dfs2)->int
		{
			ll cn = arr[cur];
			for (auto y : alist[cur])
			{
				int x = y.b;
				if (x != pa)
				{
					cn += dfs2(x, cur, dfs2);
				}
			}
			if (cn == m - l)
			{
				maxo = max(maxo, (ll)plen[cur] - plen[pa]);
			}
			return cn;//哇,差分啊当然返回总的啊
		};
		dfs2(1, 0, dfs2);
		//

		if (maxo == -1)
			return false;
		if (channel[m - 1].elen - maxo <= mid)
			return true;
		return false;
	};
	ll left = 0, right = channel[m - 1].elen;
	while (left<right)
	{
		ll mid = left + (right - left) / 2;
		if (check(mid))right = mid;
		else left = mid + 1;
	}
	//cout << left;
	write(left);
}
signed main()
{
	//ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
	int t = 1;
	//cin >> t;
	while (t--)
	{
		solve();
	}
	return 0;
}

前面部分以及差分dfs改成链式前向星就过了:

数据:

登录 - Luogu Spilopelia

其实我看了下都是遍历,邻接表也一样。这样不用push_back节省了时间吧。

//#define int ll;
const ll inf = 1e9;
const ll mod = 998244353;
const ll maxn = 300005;

inline int read()
{
	int x = 0, f = 1;
	char ch = getchar();
	while (ch < '0' || ch>'9')
	{
		if (ch == '-')
			f = -1;
		ch = getchar();
	}
	while (ch >= '0' && ch <= '9')
	{
		x = (x << 1) + (x << 3) + (ch ^ 48);
		ch = getchar();
	}
	return x * f;
}
inline void write(int x)
{
	if (x < 0)
	{
		putchar('-');
		x = -x;
	}
	if (x > 9)
		write(x / 10);
	putchar(x % 10 + '0');
}

int n, m;
struct node
{
	int b, t, next;
}nodes[2 * maxn];
struct edge
{
	int u, v;
	ll elen;
};
bool cmp(edge a, edge b)
{
	return a.elen < b.elen;
}
int k = 0;
int head[maxn];
inline void add(int a,int b,int t)
{
	k++;
	nodes[k].b = b;
	nodes[k].t = t;
	nodes[k].next = head[a];
	head[a] = k;
}
int vis[maxn];
int fa[maxn][22];
int dep[maxn];
int plen[maxn];
void dfs(int cur, int pa)
{
	dep[cur] = dep[pa] + 1;
	vis[cur] = 1;
	for (int i=head[cur];i>0;i= nodes[i].next)
	{
		int x = nodes[i].b;
		if (vis[x])continue;
		fa[x][0] = cur;
		plen[x] += nodes[i].t + plen[cur];
		dfs(x,cur);
	}
};
void solve()
{
	cin >> n >> m;
	for (int i = 0; i < n - 1; i++)
	{
		int a, b, t;
		a = read();b = read();t = read();
		add(a, b, t);
		add(b, a, t);
	}
	
	dfs(1, 0);
	//倍增求父亲
	for (int p = 1; p < 22; p++)
	{
		for (int i = 1; i <= n; i++)
		{
			fa[i][p] = fa[fa[i][p - 1]][p - 1];
		}
	}
	
	auto LCA = [&](int a, int b)->pair<int, int>
	{
		ll ans = 0;
		if (dep[a] < dep[b])swap(a, b);

		while (dep[a] > dep[b])
		{
			int dis = (int)log2(dep[a] - dep[b]);
			a = fa[a][dis];
			ans += pow(2, dis);
		}

		for (int i = log2(dep[a]); i >= 0; i--)
		{
			if (fa[a][i] != fa[b][i])	//向上结果不同才跳
			{
				a = fa[a][i];
				b = fa[b][i];
				ans += pow(2, i) * 2;
			}
		}
		if (a != b)
		{
			a = b = fa[a][0];
			ans += 2;
		}
		return { a ,ans };
	};



	vector<edge>channel(m);
	for (int i = 0; i < m; i++)
	{
		//cin >> channel[i].u >> channel[i].v;
		channel[i].u = read();
		channel[i].v = read();
		int u = channel[i].u, v = channel[i].v;
		channel[i].elen = (ll)plen[u] + plen[v] - (ll)plen[LCA(u, v).first]*2;
	}

	sort(channel.begin(), channel.end(),cmp);

	auto check = [&](int mid)->bool
	{
		int l = 0, r = m-1;
		while (l < r)
		{
			int m = l + (r - l) / 2;
			if (channel[m].elen > mid)r = m;
			else l = m+1;
		}
		// l ~ m-1 差分
		vector<int>arr(n + 1);
		for (int i = l; i < m; i++)
		{
			arr[channel[i].u]++;
			arr[channel[i].v]++;
			int f = LCA(channel[i].u, channel[i].v).first;
			arr[f] -= 2;
		}
		//priority_queue<int, vector<int>, less<int>>aedge;
		ll maxo = -1;
		auto dfs2 = [&](int cur, int pa, auto dfs2)->int
		{
			ll cn = arr[cur];
			vis[cur] = 1;
			for (int i = head[cur]; i > 0; i = nodes[i].next)
			{
				int x = nodes[i].b;
				if (vis[x])continue;
				cn += dfs2(x, cur, dfs2);
			}
			
			if (cn == m - l)
			{
				maxo = max(maxo, (ll)plen[cur] - plen[pa]);
			}
			return cn;
		};
		memset(vis, 0, sizeof vis);
		dfs2(1, 0, dfs2);
		//

		if (maxo == -1)
			return false;
		if (channel[m - 1].elen - maxo <= mid)
			return true;
		return false;
	};
	ll left = 0, right = channel[m - 1].elen;
	while (left<right)
	{
		ll mid = left + (right - left) / 2;
		if (check(mid))right = mid;
		else left = mid + 1;
	}
	//cout << left;
	write(left);
}
signed main()
{
	//ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
	int t = 1;
	//cin >> t;
	while (t--)
	{
		solve();
	}
	return 0;
}

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

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

相关文章

ASLR 和 PIE

前言 ASLR&#xff08;Address Space Layout Randomization&#xff0c;地址空间随机化&#xff09;是一种内存攻击缓解技术&#xff0c;是一种操作系统用来抵御缓冲区溢出攻击的内存保护机制。这种技术使得系统上运行的进程的内存地址无法被预测&#xff0c;使得与这些进程有…

Spring Cloud学习

1、什么是SpringCloud Spring cloud 流应用程序启动器是基于 Spring Boot 的 Spring 集成应用程序&#xff0c;提供与外部系统的集成。Spring cloud Task&#xff0c;一个生命周期短暂的微服务框架&#xff0c;用于快速构建执行有限数据处理的应用程序。Spring cloud 流应用程…

【Java设计模式】二、单例模式

文章目录 1、懒汉式2、双重检查3、静态内部类4、饿汉式5、枚举6、单例模式的破坏&#xff1a;序列化和反序列化7、单例模式的破坏&#xff1a;反射 单例模式即在程序中想要保持一个实例对象&#xff0c;让某个类只有一个实例单例类必须自己创建自己唯一的实例&#xff0c;并对外…

mysql的增删改查(常用)

增(insert) 语法&#xff1a; insert into 表名&#xff08;字段&#xff09; values( 字段对应的值) 案例&#xff1a; 创建一个学生表 结构如下&#xff1a; create table student(id int ,name varchar(20),age int); 向表中插入2条数据 create table student(id int ,n…

802.11局域网的 MAC 层协议、CSMA/CA

目录 802.11 局域网的 MAC 层协议 1 CSMA/CA 协议 无线局域网不能使用 CSMA/CD 无线局域网可以使用 CSMA 协议 802.11 的 MAC 层 分布协调功能 DCF 点协调功能 PCF CSMA/CA 协议的要点 2 时间间隔 DIFS 的重要性 SIFS DIFS 3 争用信道的过程 时隙长度的确定 退避…

Java+SpringBoot+Vue+MySQL构建银行客户管理新平台

✍✍计算机毕业编程指导师 ⭐⭐个人介绍&#xff1a;自己非常喜欢研究技术问题&#xff01;专业做Java、Python、微信小程序、安卓、大数据、爬虫、Golang、大屏等实战项目。 ⛽⛽实战项目&#xff1a;有源码或者技术上的问题欢迎在评论区一起讨论交流&#xff01; ⚡⚡ Java、…

HUAWEI Programming Contest 2024(AtCoder Beginner Contest 342)

D - Square Pair 题目大意 给一长为的数组&#xff0c;问有多少对&#xff0c;两者相乘为非负整数完全平方数 解题思路 一个数除以其能整除的最大的完全平方数&#xff0c;看前面有多少个与其余数相同的数&#xff0c;两者乘积满足条件&#xff08;已经是完全平方数的部分无…

2-22 方法、面向对象、类、JVM内存、构造方法

文章目录 方法的重载面向对象类、属性和方法成员变量默认值属性JVM简单内存分析栈空间堆空间 构造方法执行过程构造器注意点 方法的重载 一个类中名称相同&#xff0c;但是参数列表不同的方法 参数列表不同是指&#xff1a; 形参类型形参个数形参顺序 面向对象 field —— …

JAVA工程师面试专题-《JVM篇》

目录 一、运行时数据区 1、说一下JVM的主要组成部分及其作用&#xff1f; 2、说一下 JVM 运行时数据区 &#xff1f; 3、说一下堆栈的区别 4、成员变量、局部变量、类变量分别存储在什么地方&#xff1f; 5、类常量池、运行时常量池、字符串常量池有什么区别&#xff1f;…

Amazon Generative AI | 基于 Amazon 扩散模型原理的代码实践之采样篇

以前通过论文介绍 Amazon 生成式 AI 和大语言模型&#xff08;LLMs&#xff09;的主要原理之外&#xff0c;在代码实践环节主要还是局限于是引入预训练模型、在预训练模型基础上做微调、使用 API 等等。很多开发人员觉得还不过瘾&#xff0c;希望内容可以更加深入。因此&#x…

软件设计师软考题目解析05 --每日五题

想说的话&#xff1a;要准备软考了。0.0&#xff0c;其实我是不想考的&#xff0c;但是吧&#xff0c;由于本人已经学完所有知识了&#xff0c;只是被学校的课程给锁在那里了&#xff0c;不然早找工作去了。寻思着反正也无聊&#xff0c;就考个证玩玩。 本人github地址&#xf…

132.乐理基础-快速识别音程(二)

上一个内容&#xff1a;131.乐理基础-快速识别音程&#xff08;一&#xff09;-CSDN博客 上一个内容里练习的答案&#xff1a; 无论哪两个音&#xff0c;也就是无论升降记号多么离谱&#xff0c;该怎样去判断它是什么音程&#xff0c;首先就要记住&#xff08;现在只需要只需要…

es6 中的生成器 generator / 迭代器 / async /await 到底是个啥,使用场景

生成器 generator 到底是个啥 是一个函数 可以用来遍历数据结构是解决异步编程的一种方案进行数据流的生成和控制协程和状态机返回一个生成器对象/可迭代对象 生成器对象&#xff1a; 生成器对象是由生成器函数返回的对象&#xff0c;它符合迭代器协议&#xff08;Iterator Pr…

车规级MCU的行业走向

1 主要厂家 车规级MCU&#xff08;车用微控制器单元&#xff09;的主要厂家包括&#xff1a; NXP半导体&#xff1a;NXP是全球领先的车规级MCU提供商之一&#xff0c;提供广泛的产品用于汽车控制和管理系统。英飞凌科技&#xff1a;作为汽车半导体的领导者之一&#xff0c;英飞…

现代化数据架构升级:毫末智行自动驾驶如何应对年增20PB的数据规模挑战?

毫末智行是一家致力于自动驾驶的人工智能技术公司&#xff0c;其前身是长城汽车智能驾驶前瞻分部&#xff0c;以零事故、零拥堵、自由出行和高效物流为目标&#xff0c;助力合作伙伴重塑和全面升级整个社会的出行及物流方式。 在自动驾驶领域中&#xff0c;是什么原因让毫末智行…

Spring Session:Redis序列化配置|Session事件监听

Spring Session是可配置的。 Redis Configuration JSON序列化配置 Spring Session默认使用Java对象序列化机制对Session属性值进行序列化。 预定义类SysUser 先来定义一个SysUser类&#xff0c;在下面的演示案例中会用到。 package com.example.demo.model.entity;import j…

Linux环境下的性能分析 之 CPU篇(二)

2、CPU的使用情况分析 a、类似任务管理器的top & htop 说到对CPU的性能分析&#xff0c;大家一定不会忘记windows下那个最熟悉的工具&#xff1a;任务管理器。 有了这个玩意儿&#xff0c;我们就可以看到CPU的利用率&#xff0c;以及每一个进程所占用的CPU资源。那在Linu…

C++类和对象篇

1.类的定义 在C语言结构体中&#xff0c;只能定义变量&#xff0c;C扩展了类的概念&#xff0c;能够在类定义函数&#xff1b;同时&#xff0c;struct仍然可以使用&#xff0c;但更常用class来表示类 1.1类中函数的两种定义方式 函数的声明和定义都在类中 class Date { public:…

【前端素材】推荐优质后台管理系统Space平台模板(附源码)

一、需求分析 综上所述&#xff0c;后台管理系统在多个层次上提供了丰富的功能和细致的管理手段&#xff0c;帮助管理员轻松管理和控制系统的各个方面。其灵活性和可扩展性使得后台管理系统成为各种网站、应用程序和系统不可或缺的管理工具。 当我们从多个层次来详细分析后台…

【c语言】字符函数和字符串函数(上)

前言 在编程的过程中&#xff0c;我们经常要处理字符和字符串&#xff0c;为了⽅便操作字符和字符串&#xff0c;C语⾔标准库中提供了⼀系列库函数~ 欢迎关注个人主页&#xff1a;逸狼 创造不易&#xff0c;可以点点赞吗~ 如有错误&#xff0c;欢迎指出~ 目录 前言 1. 字符分…