zoukankan      html  css  js  c++  java
  • 「NOI2014」购票

    「NOI2014」购票

    解题思路

    先列出 (dp) 式子并稍微转化一下

    [dp[u] =min(dp[v]+(dis[u]-dis[v]) imes p[u] + q[u])) (dis[v]-lim[u] leq dis[u]) \ dp[u]=min(dp[v]+dis[v] imes p[u]) + p[u] imes dis[u]+q[u] \ ]

    假设有 (dis(v2)< dis(v1))(p(u))(v2) 的取值比 (v1) 优,可以得到斜率式

    [dp(v2)+p(u) imes dis(v2)leq dis(v1)+p(u) imes dp(v1) \ dfrac{dp(v2) -dp(v1)}{dis(v2)-dis(v1)}geq p(u) ]

    利用 (cdq) 的思想对有根树进行点分治,每次计算分治中心 (H) 到其祖先的一条链对其它联通块的贡献,维护一个凸包在凸包上二分即可,还挺好写的,复杂度 (mathcal O(nlog^2n))

    code

    /*program by mangoyang*/ 
    #include<bits/stdc++.h>
    #define inf ((ll)(1e18))
    #define Max(a, b) ((a) > (b) ? (a) : (b))
    #define Min(a, b) ((a) < (b) ? (a) : (b))
    typedef long long ll;
    using namespace std;
    template <class T>
    inline void read(T &x){
        int ch = 0, f = 0; x = 0;
        for(; !isdigit(ch); ch = getchar()) if(ch == '-') f = 1;
        for(; isdigit(ch); ch = getchar()) x = x * 10 + ch - 48;
        if(f) x = -x;
    }
    #define int ll
    const int N = 2000005;
    vector<int> g[N];
    int dis[N], dep[N], lim[N], dp[N], d[N], Q[N], p[N], pa[N];
    int A[N], sz[N], vis[N], pq[N], q[N], n, mn, rt, all, cnt;
    inline double slope(int x, int y){ 
    	return (double) (dp[y] - dp[x]) / (double) (dis[y] - dis[x]);
    }
    inline bool cmp(int x, int y){
    	return dis[x] - lim[x] > dis[y] - lim[y];
    }
    inline void update(int x, int y){
    	dp[x] = min(dp[y] + (dis[x] - dis[y]) * p[x] + q[x], dp[x]);
    }
    inline void prework(int u, int fa){
    	pa[u] = fa, dep[u] = dep[fa] + 1, dis[u] = dis[fa] + d[u];
    	for(int i = 0; i < (int) g[u].size(); i++)
    		if(g[u][i] != fa) prework(g[u][i], u);
    }
    inline void getsize(int u, int fa){
    	int mson = 0; sz[u] = 1;
    	for(int i = 0; i < (int) g[u].size(); i++){
    		int v = g[u][i];
    		if(vis[v] || v == fa) continue;
    		getsize(v, u), sz[u] += sz[v];
    		if(sz[v] > mson) mson = sz[v];
    	}
    	mson = max(mson, all - sz[u]);
    	if(mson < mn) mn = mson, rt = u;
    }
    inline void dfs(int u, int fa){
    	A[++cnt] = u;
    	for(int i = 0; i < (int) g[u].size(); i++)
    		if(!vis[g[u][i]] && g[u][i] != fa) dfs(g[u][i], u);
    }
    inline void divtree(int u, int top){
    	vis[u] = 1; int lst = all;
    	for(int i = 0; i < (int) g[u].size(); i++){
    		int v = g[u][i];
    		if(!vis[v] && v == pa[u]){
    			mn = all = sz[v] > sz[u] ? lst - sz[u] : sz[v];
    			getsize(v, u), divtree(rt, top);
    		}
    	}	
    	for(int s = pa[u]; s != pa[top]; s = pa[s]) 
    		if(dis[u] - dis[s] <= lim[u]) update(u, s);
    	cnt = 0;
    	for(int i = 0; i < (int) g[u].size(); i++){
    		int v = g[u][i];
    		if(!vis[v]) dfs(v, u);
    	}
    	sort(A + 1, A + cnt + 1, cmp);
    	int t = 0; int s = u;
    	for(int i = 1; i <= cnt; i++){
    		while(s != pa[top] && dis[A[i]] - lim[A[i]] <= dis[s]){
    			while(t > 1 && slope(Q[t-1], Q[t]) <= slope(Q[t-1], s)) t--;
    			Q[++t] = s, s = pa[s];
    		}
    		int l = 1, r = t - 1, res = 1;
    		while(l <= r){
    			int mid = (l + r) >> 1;
    			if(slope(Q[mid], Q[mid+1]) >= (double) p[A[i]]) 
    				res = l = mid + 1;
    			else r = mid - 1;
    		}
    		if(res <= t) update(A[i], Q[res]);
    	}
    	for(int i = 0; i < (int) g[u].size(); i++){
    		int v = g[u][i];
    		if(vis[v]) continue;
    		mn = all = sz[v] > sz[u] ? lst - sz[u] : sz[v];
    		getsize(v, u), divtree(rt, v);
    	}
    }
    signed main(){
    	read(n); int type; read(type);
    	for(int i = 2, x; i <= n; i++){
    		read(x), read(d[i]), read(p[i]);
    		read(q[i]), read(lim[i]), dp[i] = inf;
    		g[x].push_back(i), g[i].push_back(x);
    	}
    	prework(1, 0);
    	mn = all = n, getsize(1, 0), divtree(rt, 1);
    	for(int i = 2; i <= n; i++) printf("%lld
    ", dp[i]);
    	return 0;
    }
    
  • 相关阅读:
    DRF项目创建流程(1)
    RESTful API规范
    超哥笔记--shell 基本命令(4)
    转:django模板标签{% for %}的使用(含forloop用法)
    自定django登录跳转限制
    jquery Ajax应用
    js重定向跳转页面
    django项目mysql中文编码问题
    python进阶(六) 虚拟环境git clone报错解决办法
    Linux基础(六) Vim之vundle插件
  • 原文地址:https://www.cnblogs.com/mangoyang/p/10519355.html
Copyright © 2011-2022 走看看