zoukankan      html  css  js  c++  java
  • day26T3改错记

    题目描述

    定义一次操作为以(1)为根,选两个互相不为祖先的节点,交换它们的子树

    定义一棵树的权值为至多进行一次操作的最大直径长度

    初始只有节点(1),依次插入(2)(n)号节点(作为已经存在的某个点的儿子),问每次插入后树的权值

    强制在线

    (1 le n le 2e5),保证任意时刻树的形态合法

    解析

    容易发现使直径最大的操作方式是把与直径不想交的最长链接在直径的一端

    其实不用在意祖先关系的限制,因为如果不合法你总可以选具有祖先关系两个点当“直径”的端点,另外一个点所在的链砍下来接过去

    然后权值就转化成树上选(3)个点,两两距离之和(/2 - 1)再和直径取个(max),直径端点又一定在这(3)个点中

    然后每次新加点就可以枚举它替换了原答案中的哪个点,和原答案选个最优的更新

    又由于每次插入的节点一定是叶子,可以简单地维护深度和倍增(LCA)

    代码

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <vector>
    #define MAXN 200005
    
    typedef long long LL;
    
    char gc();
    int read();
    int LCA(int, int);
    int dist(int, int);
    void update(int);
    
    int N, ans, anc[MAXN][20], dep[MAXN], p, q, r, dpq, dpr, dqr;
    
    int main() {
    	freopen("forest.in", "r", stdin);
    	freopen("forest.out", "w", stdout);
    
    	read(), N = read();
    	p = q = r = 1;
    	dpq = dpr = dqr = 0;
    	for (int i = 2; i <= N; ++i) {
    		anc[i][0] = read() ^ ans;
    		dep[i] = dep[anc[i][0]] + 1;
    		for (int j = 1; j < 20; ++j) {
    			anc[i][j] = anc[anc[i][j - 1]][j - 1];
    			if (!anc[i][j]) break;
    		}
    		update(i);
    
    		//local test
    		//printf("%d
    ", ans);
    		printf("%d
    ", ans);
    	}
    
    	return 0;
    }
    inline char gc() {
    	static char buf[1000000], *p1, *p2;
    	if (p1 == p2) p1 = (p2 = buf) + fread(buf, 1, 1000000, stdin);
    	return p1 == p2 ? EOF : *p2++;
    }
    inline int read() {
    	int res = 0; char ch = gc();
    	while (ch < '0' || ch > '9') ch = gc();
    	while (ch >= '0' && ch <= '9') res = (res << 1) + (res << 3) + ch - '0', ch = gc();
    	return res;
    }
    int LCA(int x, int y) {
    	if (dep[x] < dep[y]) std::swap(x, y);
    	for (int i = 19; i >= 0; --i)
    		if (dep[anc[x][i]] >= dep[y]) x = anc[x][i];
    	if (x == y) return x;
    	for (int i = 19; i >= 0; --i)
    		if (anc[x][i] ^ anc[y][i])
    			x = anc[x][i], y = anc[y][i];
    	return anc[x][0];
    }
    int dist(int x, int y) {
    	int lca = LCA(x, y);
    	return dep[x] + dep[y] - (dep[lca] << 1);
    }
    void update(int nx) {
    	int dis1 = dist(nx, p), dis2 = dist(nx, q), dis3 = dist(nx, r);
    	int ans1 = std::max(std::max(dpq, dis1), std::max(dis2, ((dpq + dis1 + dis2) >> 1) - 1));
    	int ans2 = std::max(std::max(dis1, dpr), std::max(dis3, ((dis1 + dpr + dis3) >> 1) - 1));
    	int ans3 = std::max(std::max(dis2, dis3), std::max(dqr, ((dis2 + dis3 + dqr) >> 1) - 1));
    	if (ans1 >= ans2 && ans1 >= ans3 && ans1 >= ans) {
    		r = nx, dpr = dis1, dqr = dis2;
    		ans = ans1;
    	} else if (ans2 >= ans1 && ans2 >= ans3 && ans2 >= ans) {
    		q = nx, dpq = dis1, dqr = dis3;
    		ans = ans2;
    	} else if (ans3 >= ans) {
    		p = nx, dpq = dis2, dpr = dis3;
    		ans = ans3;
    	}
    }
    //Rhein_E 100pts
    
  • 相关阅读:
    自己在安装centos 系统时, 是使用英文安装 成功,现在系统语言为英语,如何设置为中文?
    【转】HTML5的语音输入 渐进使用HTML5语言识别, so easy!
    基于layer简单的弹层封装
    条码扫描仪前端驱动
    JavaScript 生成Guid函数
    数据库连接字符串
    IDatabaseInitializer<TContext>接口研究
    async与await线程分配研究
    AsyncLocal<T>与ThreadLocal<T>区别研究
    entity framework core 2.0 & sqlite 配置教程
  • 原文地址:https://www.cnblogs.com/Rhein-E/p/10622489.html
Copyright © 2011-2022 走看看