zoukankan      html  css  js  c++  java
  • 【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
    ", 1.0 * ans / 2);
    	return 0;
    }
    

  • 相关阅读:
    原来 Sql Server 的存储过程是可以调试的
    网站SEO优化之如何发布外链
    7个有助于SEO优化的网站文章编辑技巧
    技术峰会2005
    SHA1算法告破
    Google Suggest
    Photo Story 3 for Windows XP
    SQL Server 2005: 价格和开源
    抱歉,昨天加班未能参加讨论
    2GB Hotmail comes!
  • 原文地址:https://www.cnblogs.com/abclzr/p/5785335.html
Copyright © 2011-2022 走看看