zoukankan      html  css  js  c++  java
  • 题解:「COCI2019」 Transport

    题面

    树上点对问题考虑点分治。

    按照套路讨论经过一个点 (p) 的路径的情况。

    对于这道题的每一个点对 ((u,v)) 的路径可以分为 (u ightarrow p)(p ightarrow v) 两段。

    对于前者,需要知道走完这条路径后剩余的油量,记作 (L_{u ightarrow p})

    对于后者,需要知道在允许油量小于 0 时,走这条路径时油量的最小值,记作 (R_{p ightarrow v})

    这样只要满足 (L_{u ightarrow p} + R_{p ightarrow v} geq 0) 时,点对 ((u,v)) 成立。

    处理出 (L)(R) 后,将两者暴力排序,之后用双指针扫一遍就行了,不要忘了用容斥或者染色法避免重复计数。

    时间复杂度 (mathcal{O}(nlog_2^2 n))

    Code(C++):

    #include<bits/stdc++.h>
    #define forn(i,s,t) for(register int i=(s);i<=(t);++i)
    using namespace std;
    typedef long long LL;
    const int N = 1e5+1e3;
    template<typename T>inline T Max(T A, T B) {return A>B?A:B;}
    template<typename T>inline T Min(T A, T B) {return A<B?A:B;}
    struct List {int dir, nxt; LL lng; } E[N<<1];
    int G[N], cnt;
    inline void Add(int u, int v, LL w) {
    	E[++cnt].dir = v, E[cnt].nxt = G[u], G[u] = cnt;
    	E[cnt].lng = w;
    }
    int n; LL a[N], Ans;
    bool vis[N];
    int Mx[N], sz[N], rt, S;
    void Getrt(int u, int fa) { // 找重心 
    	sz[u] = 1, Mx[u] = 0;
    	for(int i=G[u];i;i=E[i].nxt) {
    		int v = E[i].dir;
    		if(vis[v] || v == fa) continue ;
    		Getrt(v, u);
    		sz[u] += sz[v];
    		Mx[u] = Max(Mx[u], sz[v]);
    	}
    	Mx[u] = Max(Mx[u], S - sz[u]);
    	(Mx[u] < Mx[rt]) && (rt = u);
    }
    LL L[N], R[N];
    int f[N], l, r, Cl[N], Cr[N], now, Nu, idl[N], idr[N];
    inline bool cmpl(int A, int B) {return L[A] < L[B];}
    inline bool cmpr(int A, int B) {return R[A] < R[B];}
    void dfs(int u, int fa, LL dist, LL Dn, LL Up) {
    	if(Up == 0) L[++l] = dist, Cl[l] = now;
    	R[++r] = -Dn, Cr[r] = now;
    	for(int i=G[u];i;i=E[i].nxt) {
    		int v = E[i].dir; LL w = E[i].lng;
    		if(vis[v] || v == fa) continue ;
    		dfs(v, u, dist - w + a[v], Min(Dn, dist - a[Nu] - w), Min(0ll, Up - w + a[v]));
    	}
    }
    void calc(int u) {
    	l = r = 0, Nu = u;
    	L[++l] = a[u], Cl[l] = u, f[u] = 0;
    	R[++r] = 0, Cr[r] = u;
    	for(int i=G[u];i;i=E[i].nxt) {
    		int v = E[i].dir; LL w = E[i].lng;
    		if(vis[v]) continue ;
    		now = v; f[now] = 0;
    		dfs(v, u, a[u] + a[v] - w, -w, Min(0ll, - w + a[v]));
    	}
    	forn(i,1,l) idl[i] = i; sort(idl+1, idl+l+1, cmpl);
    	forn(i,1,r) idr[i] = i; sort(idr+1, idr+r+1, cmpr);
    	int j = 1;
    	forn(i,1,l) {	// 2 Pnt 
    		while(j <= r && R[idr[j]] <= L[idl[i]]) f[Cr[idr[j++]]] ++ ;
    		Ans += j - 1 - f[Cl[idl[i]]];
    	}
    }
    void solve(int u) {
    	vis[u] = 1;
    	calc(u);
    	for(int i=G[u];i;i=E[i].nxt) {
    		int v = E[i].dir;
    		if(vis[v]) continue ;
    		S = sz[v] > sz[u] ? n - sz[u] : sz[v];
    		rt = 0, Getrt(v, v);
    		solve(rt);
    	}
    }
    int main() {
    	scanf("%d", &n);
    	forn(i,1,n) scanf("%lld", a+i);
    	forn(i,2,n) {
    		int u, v; LL w;
    		scanf("%d%d%lld", &u, &v, &w);
    		Add(u, v, w), Add(v, u, w);
    	}
    	S = Mx[rt = 0] = n;
    	Getrt(1, 1);
    	solve(rt);
    	printf("%lld
    ", Ans);
    	return 0;
    } 
    
  • 相关阅读:
    bilibili 高并发实时弹幕系统的实现
    主流深度学习框架对比
    完整的视频直播系统
    一个简单的直播demo for java
    流媒体知识 wiki
    Entity Framework 6 暂停重试执行策略
    泛型的资源释放
    Entity Framework异步查询和保存
    Entity Framework中的连接管理
    了解Entity Framework中事务处理
  • 原文地址:https://www.cnblogs.com/Ax-Dea/p/14453016.html
Copyright © 2011-2022 走看看