首页 > 其他分享 >Luogu T273083 新的题目 题解

Luogu T273083 新的题目 题解

时间:2022-09-20 19:55:05浏览次数:67  
标签:int 题解 复杂度 times T273083 Luogu qn 优化 dis

怕放洛谷有人看,就搬过来了。

本题解提供一个 \(O(qn)\) 的做法(实际上是暴力的优化)。

先考虑暴力求解。

对于每个操作,要求代价 \(W \times (\sum_{i \in X}^{i} w[i] \times dis[i][x] + \sum_{j \in Y}^{j} w[j] \times dis[j][y])\),我们需要对每个 \(i\) 或 \(j\) 都求一遍 \(dis[i][x]\) 或 \(dis[j][y]\)。而这个过程大约是 \(O(n)\) 的。加上每次操作最多有 \(n\) 个点,时间复杂度 \(O(qn^2)\)。

这个复杂度显然是不能接受的。因此考虑如何优化。

操作的点数和总操作数是无法优化的,所以我们尝试对求 \(dis\) 的过程优化。

如果在树上有一个定点 \(x\),我们可以以它为根进行 dfs,这样可以在 \(O(n)\) 时间内求出所有其它点的“深度”,也就是我们要的 \(dis\)。

因为树上任意两点间的路径有且只有一条,进行操作只会使原本有的路径消失而不会增加新的路径。

那么我们就能够直接在进行操作前对于每个 \(i \in [1, n]\) 进行 dfs,预处理出树上任意两点间的距离。预处理复杂度 \(O(n^2)\),需要时 \(O(1)\) 查表即可。

于是我们优化掉了 \(O(n)\) 的复杂度,剩下 \(O(qn)\),足以通过 \(n,q \le 5 \times 10^3\) 的数据。

注意到毒瘤出题人(我不说是谁)卡了本题的空间,实现时要当心。

放一个不开会 O2 T 飞的屑代码。

Code

#include <bits/stdc++.h> 
using namespace std;
const int N = 5e3 + 10;
map <pair<int, int>, bool> mp1;
map <pair<int, int>, int> mp2;
int dis[N][N], w[N];
struct node
{
	int to, next, value;
}e[N << 1];
int head[N];
bool vis[N];
int tot;
long long res, ans;
inline int read()
{
	register int r = 0, c = getchar(), f = 1;
	while (c < '0' || c > '9')
	{
		if (c == '-') f = -1;
		c = getchar();
	}
	while (c >= '0' && c <= '9') r = (r << 3) + (r << 1) + (c ^ 48), c = getchar();
	return r * f;
}
inline void add(int u, int v, int w)
{
	e[++tot].to = v;
	e[tot].value = w;
	e[tot].next = head[u];
	mp2[{u, v}] = w;
	head[u] = tot;
}
void dfs(int now, int rt)
{
	vis[now] = 1;
	for (int i = head[now]; i; i = e[i].next)
	{
		int y = e[i].to;
		if (!vis[y]) 
		{
			dis[y][rt] = dis[now][rt] + e[i].value;
			dfs(y, rt);
		}
	}
}
void dfs2(int now, int rt)
{
	vis[now] = 1;
	res += w[now] * 1ll * dis[now][rt];
	for (int i = head[now]; i; i = e[i].next)
	{
		register int y = e[i].to;
		if (!mp1[{now, y}] && !vis[y]) dfs2(y, rt);
	}
}
int main()
{
	register int n = read();
	for (register int i = 1; i <= n; ++i) w[i] = read();
	for (register int i = 1; i < n; ++i) 
	{
		register int x = read(), y = read(), z = read();
		add(x, y, z);
		add(y, x, z);
	}
	for (register int i = 1; i <= n; ++i) 
	{
		memset(vis, 0, sizeof vis);
		dfs(i, i);
	}
//	for (int i = 1; i <= n; ++i) 
//	{
//		for (int j = 1; j <= n; ++j) printf("%d ", dis[i][j]);
//		puts(""); 
//	}
	register int q = read();
	while (q--)
	{
		res = 0;
		register int u = read(), v = read();
		mp1[{u, v}] = mp1[{v, u}] = 1;
		memset(vis, 0, sizeof vis);
		dfs2(u, u);
		memset(vis, 0, sizeof vis);
		dfs2(v, v);
//		printf("\n%d\n", res);
		res *= mp2[{u, v}];
		ans ^= res;
	}
	printf("%lld\n", ans);
	return 0;
}

标签:int,题解,复杂度,times,T273083,Luogu,qn,优化,dis
From: https://www.cnblogs.com/tzy-tmy/p/16712274.html

相关文章

  • CF1363F题解
    好妙的dp-1的情况就是字母构成的可重集不同我们将一次操作抽象成将一个字符向前移动若干格我们设f[i][j]表示s串到了第i个字母,t串到了第j个字母的最小操作次数1.将第i......
  • luogu 将会臭名昭著(
    ......
  • Codeforces #821 Div2(A~D2)题解
    CF#821Div2AConsecutiveSum题目:​ 选择\(i\)和\(j\),如果\(j=i+xk(x=R)\),可以交换\(i,j\)。任意选择一段长度为k的相加。思路:​ 题目等价于在下标\(mod\)k相同......
  • CGR1 简要题解
    G.Tree-Tac-Toe瞎扯:首先一看黑就不可能赢,最多争个平。若有度数大于\(3\)的点白直接赢了。若一个点度数为\(3\),且只有不多于\(1\)端是叶子,白也赢了。所以现在树的形......
  • js精度计算问题解决,Jsutil库源码
    为什么会存在浮点数计算精度丢失问题,这个原因不再过多赘述; JS中如何解决精度计算问题,大不部分人都知道升幂再降幂的解决方案; 但是如果直接升幂也会出现精度问题,且需......
  • sb课件的题解(复习)
    sb课件的题解(复习)不理解,为什么一个新的课件我就2题没做过,没救了CF1310C这题,我们发现它不同的子段共有\(n*(n-1)/2\)个,将其按字典序排序我们需要便捷的比较,考虑维护\(......
  • 【题解】CF1733E - Conveyor
    因为每秒只放一个球,所以对于每一个\(x+y=a\)的对角线最多只有一个球且任意两个球不会相遇,所以我们只用知道第\(t-x-y\)秒放的球的移动路径即可。等价于需要求出前\(......
  • CF round 812 div2 A-D 题解
    首先第一题TravelingSalesManProblem,给出一些坐标,就是问从原点出发,然后收集所有的点,问最少需要多少次移动这个就是求收集完那曼哈顿距离,这个距离稍加观察可以发现,就是......
  • EFCore 6级联删除问题解决Database operation expected to affect 1 row(s) but actua
    异常信息:Databaseoperationexpectedtoaffect1row(s)butactuallyaffected0row(s).Datamayhavebeenmodifiedordeletedsinceentitieswereloaded.See......
  • SP2128题解
    题意共有\(t\)个\(n\timesm\)的由.、x、o组成的字符矩阵。设矩阵中连续\(k\)格为x小A加一分,连续\(k\)格为o小B加一分。正文\(\Large{时间复杂度:}\l......