• CSP模拟赛 Lost My Music(二分,可回退化栈)


    题面

    在这里插入图片描述

    题解

    发现是斜率的形式,答案的相反数可以看做一条直线的斜率。那么我们要答案最小,斜率最大。维护下凸壳就行了。

    考试时写了直接dfsdfs+暴力弹栈拿了8080分(还以为自己是O(n)正解美滋滋

    就是直接存下根到当前点的路径上的凸包,然后回退的时候撤销操作。但这样一个点可能在子树下面被弹出多次。所以最坏情况是O(n2)O(n^2)的(链+菊花)。

    考虑怎么实现可回退化栈。可以写倍增(我不会),但是发现可以在凸包上二分到该插入的位置,然后直接存一下被删除的第一个点,然后直接把那个位置设为当前点。回退的时候修改回来就行了。这样每次只改一个点。但是由于要二分,还是O(nlogn)O(nlog n)的。

    CODE

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    inline void read(int &x) {
    	char ch; while(!isdigit(ch=getchar()));
    	for(x=ch-'0';isdigit(ch=getchar());x=x*10+ch-'0');
    }
    const int MAXN = 500005;
    int n, x[MAXN], y[MAXN], fa[MAXN], fir[MAXN], to[MAXN], nxt[MAXN], cnt;
    inline void link(int u, int v) { to[++cnt] = v; nxt[cnt] = fir[u]; fir[u] = cnt; }
    int q[MAXN];
    double ans[MAXN];
    
    inline LL Cross(LL a, LL b, LL c, LL d) { return a*d - b*c; }
    
    int find(int i, int r) {
    	int l = 2, mid, re = r+1;
    	while(l <= r) {
    		mid = (l + r) >> 1;
    		if(Cross(x[i]-x[q[mid-1]], y[i]-y[q[mid-1]], x[i]-x[q[mid]], y[i]-y[q[mid]]) <= 0) re = mid, r = mid-1;
    		else l = mid+1;
    	}
    	ans[i] = (double)(y[q[re-1]]-y[i]) / (double)(x[i]-x[q[re-1]]);
    	return re;
    }
    void dfs(int u, int now) {
    	x[u] = x[fa[u]] + 1;
    	int pos = now ? find(u, now) : 1, id = q[pos];
    	q[pos] = u;
    	for(int i = fir[u]; i; i = nxt[i])
    		dfs(to[i], pos);
    	q[pos] = id;
    }
    int main () {
    	freopen("lost.in", "r", stdin);
    	freopen("lost.out", "w", stdout);
    	read(n);
    	for(int i = 1; i <= n; ++i) read(y[i]);
    	for(int i = 2; i <= n; ++i) read(fa[i]), link(fa[i], i);
    	dfs(1, 0);
    	for(int i = 2; i <= n; ++i) printf("%.10f
    ", ans[i]);
    }
    
  • 相关阅读:
    关于VGG网络的介绍
    nvidia-docker 安装
    test
    ARTS-S EN0002-London HIV patient's remission spurs hope for curing AIDS
    ARTS-S EN0001-In tech race with China, US universities may lose a vital edge
    ARTS-S Why do India and Pakistan keep fighting over Kashmir?
    ARTS-S sed指定行添加
    ARTS-S linux查看进程打开的文件数
    ARTS-S centos查看端口被哪个进程占用
    ARTS-S centos修改hostname
  • 原文地址:https://www.cnblogs.com/Orz-IE/p/12039181.html
Copyright © 2020-2023  润新知