【BZOJ 3242】【UOJ #126】【CodeVS 3047】【NOI 2013】快餐店

http://www.lydsy.com/JudgeOnline/problem.php?id=3242

http://uoj.ac/problem/126

http://codevs.cn/problem/3047/

因为存在一条边,答案所在的点走向左右的城的最短路都不会经过这条边。

所以枚举这条边,剩下的用线段树维护。

线段树初始化搞了好久,忘了在外向树上做dp,树形dp时记录也错了,总之调了一天,吃枣药丸啊QwQ

时间复杂度$O(nlogn)$,听说有$O(n)$的单调队列做法,留一个坑以后再看。

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
const int N = 100003;
int in() {
	int k = 0, fh = 1; char c = getchar();
	for(; c < ‘0‘ || c > ‘9‘; c = getchar())
		if (c == ‘-‘) fh = -1;
	for(; c >= ‘0‘ && c <= ‘9‘; c = getchar())
		k = (k << 3) + (k << 1) + c - ‘0‘;
	return k * fh;
}

struct SegmentTree {
	int L, R, n, maid[N << 2];
	ll ma[N << 2], ma_sc[N << 2], lazy[N << 2], key;
	void pushdown(int rt, int l, int r) {
		if (lazy[rt]) {
			ma[rt << 1] += lazy[rt];
			ma[rt << 1 | 1] += lazy[rt];
			if (l != r) {
				ma_sc[rt << 1] += lazy[rt];
				ma_sc[rt << 1 | 1] += lazy[rt];
			}
			lazy[rt << 1] += lazy[rt];
			lazy[rt << 1 | 1] += lazy[rt];
			lazy[rt] = 0;
		}
	}
	void pushup(int rt) {
		if (ma[rt << 1] > ma[rt << 1 | 1]) ma[rt] = ma[rt << 1], maid[rt] = maid[rt << 1];
		else ma[rt] = ma[rt << 1 | 1], maid[rt] = maid[rt << 1 | 1];
		if (ma[rt << 1] > ma[rt << 1 | 1]) ma_sc[rt] = max(ma[rt << 1 | 1], ma_sc[rt << 1]);
		else ma_sc[rt] = max(ma[rt << 1], ma_sc[rt << 1 | 1]);
	}
	void mkmaid(int rt, int l, int r, ll *s) {
		lazy[rt] = 0;
		if (l == r) {
			maid[rt] = l;
			ma[rt] = s[l];
			ma_sc[rt] = -10000000000000000ll;
			return;
		}
		int mid = (l + r) >> 1;
		mkmaid(rt << 1, l, mid, s);
		mkmaid(rt << 1 | 1, mid + 1, r, s);
		pushup(rt);
	}
	void init(int num, ll *s) {
		n = num;
		mkmaid(1, 1, n, s);
	}
	void update(int rt, int l, int r) {
		if (L <= l && r <= R) {
			lazy[rt] += key;
			ma[rt] += key;
			if (l != r) ma_sc[rt] += key;
			return;
		}
		int mid = (l + r) >> 1;
		pushdown(rt, l, r);
		if (L <= mid) update(rt << 1, l, mid);
		if (R > mid) update(rt << 1 | 1, mid + 1, r);
		pushup(rt);
	}
	void cover(int l, int r, ll num) {
		L = l; R = r; key = num;
		update(1, 1, n);
	}
} T1, T2;

struct node {
	int nxt, to, w;
} E[N << 1];
bool vis[N];
ll g[N], sum1[N], sum2[N], Treefr[N], Treesc[N];
int n, cnt = 0, point[N], fa[N], fadis[N], mark = 0, markf;
int cir[N], cirnum, cirdis[N], lala;

void ins(int u, int v, int l) {E[++cnt] = (node) {point[u], v, l}; point[u] = cnt;}

void dfs(int x) {
	vis[x] = true;
	for(int i = point[x]; i; i = E[i].nxt)
		if (E[i].to != fa[x]) {
			if (vis[E[i].to]) {
				mark = x;
				markf = E[i].to;
				lala = E[i].w;
				return;
			}
			fa[E[i].to] = x; fadis[E[i].to] = E[i].w;
			dfs(E[i].to);
			if (mark) return;
		}
}

ll ans2 = 0;

ll dfs2(int x) {
	ll ret = 0; vis[x] = true;
	for(int i = point[x]; i; i = E[i].nxt)
		if (!vis[E[i].to]) {
			ret = max(ret, dfs2(E[i].to) + E[i].w);
			if (Treefr[E[i].to] + E[i].w >= Treefr[x]) {
				Treesc[x] = Treefr[x];
				Treefr[x] = Treefr[E[i].to] + E[i].w;
			} else if (Treefr[E[i].to] + E[i].w > Treesc[x])
				Treesc[x] = Treefr[E[i].to] + E[i].w;
		}
	ans2 = max(ans2, Treefr[x] + Treesc[x]);
	return ret;
}

ll Query() {
	if (T1.maid[1] == T2.maid[1]) return max(T1.ma[1] + T2.ma_sc[1], T1.ma_sc[1] + T2.ma[1]);
	else return T1.ma[1] + T2.ma[1];
}

int main() {
	n = in();
	int u, v, l;
	for(int i = 1; i <= n; ++i) {
		u = in(); v = in(); l = in();
		ins(u, v, l);
		ins(v, u, l);
	}

	fa[1] = 0; dfs(1);
	cir[1] = markf;
	cir[2] = mark;
	cirdis[1] = lala;
	cirnum = 2;
	memset(vis, 0, sizeof(bool) * (n + 1));
	vis[mark] = true;
	while (mark != markf) {
		cirdis[cirnum] = fadis[mark];
		mark = fa[mark]; vis[mark] = true;
		cir[++cirnum] = mark;
	}
	cirdis[cirnum] = cirdis[1]; cirdis[0] = cirdis[cirnum - 1];

	for(int i = 1; i < cirnum; ++i)
		g[i] = dfs2(cir[i]);

	ll ret = 0, ans;
	for(int i = 1; i < cirnum; ++i) {
		sum1[i] = g[i] + ret;
		sum2[i] = g[i] - ret;
		ret += cirdis[i];
	}
	T1.init(cirnum - 1, sum1); T2.init(cirnum - 1, sum2);
	ans = Query();

	for(int i = 2; i < cirnum; ++i) {
		T1.cover(i - 1, i - 1, ret);
		T2.cover(i - 1, i - 1, -ret);
		T1.cover(1, cirnum - 1, -cirdis[i - 1]);
		T2.cover(1, cirnum - 1, cirdis[i - 1]);
		ans = min(ans, Query());
	}

	ans = max(ans, ans2);
	printf("%.1lf\n", 1.0 * ans / 2);
	return 0;
}

时间: 2024-10-09 13:49:51

【BZOJ 3242】【UOJ #126】【CodeVS 3047】【NOI 2013】快餐店的相关文章

【BZOJ3242】【UOJ#126】【NOI2013】快餐店

NOI都是这种难度的题怎么玩嘛QAQ 原题: 小T打算在城市C开设一家外送快餐店.送餐到某一个地点的时间与外卖店到该地点之间最短路径长度是成正比的,小T希望快餐店的地址选在离最远的顾客距离最近的地方. 快餐店的顾客分布在城市C的N 个建筑中,这N 个建筑通过恰好N 条双向道路连接起来,不存在任何两条道路连接了相同的两个建筑.任意两个建筑之间至少存在一条由双向道路连接而成的路径.小T的快餐店可以开设在任一建筑中,也可以开设在任意一条道路的某个位置上(该位置与道路两端的建筑的距离不一定是整数). 现

【BZOJ 3672】【UOJ #7】【NOI 2014】购票

http://www.lydsy.com/JudgeOnline/problem.php?id=3672 http://uoj.ac/problem/7 链上的情况可以用斜率优化dp.树上用斜率优化dp时,单调队列的复杂度是均摊$O(n)$的,所以放到树上做“可持久化单调队列”复杂度是$O(n^2)$的,所以不能树上斜率优化. 这道题可以用树链剖分(时间复杂度$O(nlog^3n)$)或者点分治套cdq分治(时间复杂度$O(nlog^2n)$).因为树链剖分感觉比较难写,而且每个节点用vecto

洛谷 P2827 BZOJ 4721 UOJ #264 蚯蚓

题目描述 本题中,我们将用符号表示对c向下取整,例如:. 蛐蛐国最近蚯蚓成灾了!隔壁跳蚤国的跳蚤也拿蚯蚓们没办法,蛐蛐国王只好去请神刀手来帮他们消灭蚯蚓. 蛐蛐国里现在共有n只蚯蚓(n为正整数).每只蚯蚓拥有长度,我们设第i只蚯蚓的长度为,并保证所有的长度都是非负整数(即:可能存在长度为0的蚯蚓). 每一秒,神刀手会在所有的蚯蚓中,准确地找到最长的那一只(如有多个则任选一个)将其切成两半.神刀手切开蚯蚓的位置由常数p(是满足0<p<1的有理数)决定,设这只蚯蚓长度为x,神刀手会将其切成两只长度

UOJ#126【NOI2013】快餐店

[NOI2013]快餐店 链接:http://uoj.ac/problem/126 YY了一个线段树+类旋转卡壳的算法.骗了55分.还比不上$O(n^2)$暴力T^T 题目实际上是要找一条链的两个端点,链的中点处建快餐店.要求这两个端点的最短距离为其他所有点对的最短距离的最大值. 这条链不经过环,那答案就是环上挂的某个子树的子树直径.至少大于等于最大的树直径.树DP一发得到Ans1 经过环,显然不会饶环一圈.这个链必定由这样构成:x,y为环上两点.x子树最长链->x-y最短路-y子树最长链.可以

bzoj 3242: [Noi2013]快餐店 章鱼图

3242: [Noi2013]快餐店 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 266  Solved: 140[Submit][Status] Description 小 T打算在城市C开设一家外送快餐店.送餐到某一个地点的时间与外卖店到该地点之间最短路径长度是成正比的,小T希望快餐店的地址选在离最远的顾客距离最近 的地方. 快餐店的顾客分布在城市C的N 个建筑中,这N 个建筑通过恰好N 条双向道路连接起来,不存在任何两条道路连接了相同的两

[POJ 1185][codevs 1647][NOI 2001]炮兵阵地 状压DP

炮兵阵地 Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 23655 Accepted: 9148 Description 司令部的将军们打算在N*M的网格地图上部署他们的炮兵部队.一个N*M的地图由N行M列组成,地图的每一格可能是山地(用"H" 表示),也可能是平原(用"P"表示),如下图.在每一格平原地形上最多可以布置一支炮兵部队(山地上不能够部署炮兵部队):一支炮兵部队在地图上的攻击范围如图

[BZOJ 3668&amp;UOJ #2][Noi2014]起床困难综合症(贪心)

Description 21 世纪,许多人得了一种奇怪的病:起床困难综合症,其临床表现为:起床难,起床后精神不佳.作为一名青春阳光好少年,atm 一直坚持与起床困难综合症作斗争.通过研究相关文献,他找到了该病的发病原因:在深邃的太平洋海底中,出现了一条名为 drd 的巨龙,它掌握着睡眠之精髓,能随意延长大家的睡眠时间.正是由于 drd 的活动,起床困难综合症愈演愈烈,以惊人的速度在世界上传播.为了彻底消灭这种病,atm 决定前往海底,消灭这条恶龙.历经千辛万苦,atm 终于来到了 drd 所在的

bzoj 3816&amp;&amp;uoj #41. [清华集训2014]矩阵变换

稳定婚姻问题: 有n个男生,n个女生,所有女生在每个男生眼里有个排名,反之一样. 将男生和女生两两配对,保证不会出现婚姻不稳定的问题. 即A-1,B-2 而A更喜欢2,2更喜欢A. 算法流程: 每次男生向自己未追求过的排名最高女生求婚. 然后每个有追求者的女生在自己现男友和追求者中选择一个最喜欢的接受,然后拒绝其他人. 算法一定可以结束. 因为如果最后有一个男生单身,那他一定把所有女生都追求过一遍,说明没有女生单身,产生矛盾. #include<iostream> #include<cs

bzoj 3242: [Noi2013]快餐店

Description 小T打算在城市C开设一家外送快餐店.送餐到某一个地点的时间与外卖店到该地点之间最短路径长度是成正比的,小T希望快餐店的地址选在离最远的顾客距离最近的地方. 快餐店的顾客分布在城市C的N 个建筑中,这N 个建筑通过恰好N 条双向道路连接起来,不存在任何两条道路连接了相同的两个建筑.任意两个建筑之间至少存在一条由双向道路连接而成的路径.小T的快餐店可以开设在任一建筑中,也可以开设在任意一条道路的某个位置上(该位置与道路两端的建筑的距离不一定是整数). 现给定城市C的地图(道路