【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;
}

posted @ 2016-08-18 20:51  abclzr  阅读(249)  评论(0编辑  收藏  举报