• P4116 Qtree3


    (color{#0066ff}{ 题目描述 })

    给出N个点的一棵树(N-1条边),节点有白有黑,初始全为白

    有两种操作:

    0 i : 改变某点的颜色(原来是黑的变白,原来是白的变黑)

    1 v : 询问1到v的路径上的第一个黑点,若无,输出-1

    (color{#0066ff}{输入格式})

    第一行 N,Q,表示N个点和Q个操作

    第二行到第N行N-1条无向边

    再之后Q行,每行一个操作"0 i" 或者"1 v" (1 ≤ i, v ≤ N).

    (color{#0066ff}{输出格式})

    对每个1 v操作输出结果。

    (color{#0066ff}{输入样例})

    9 8
    1 2
    1 3
    2 4
    2 9
    5 9
    7 9
    8 9
    6 8
    1 3
    0 8
    1 6
    1 7
    0 2
    1 9
    0 2
    1 9 
    

    (color{#0066ff}{输出样例})

    -1
    8
    -1
    2
    -1
    

    (color{#0066ff}{数据范围与提示})

    For 1/3 of the test cases, N=5000, Q=400000.

    For 1/3 of the test cases, N=10000, Q=300000.

    For 1/3 of the test cases, N=100000, Q=100000.

    (color{#0066ff}{ 题解 })

    树剖||LCT

    LCT,维护当前点颜色,和Splay子树颜色有无黑色,平衡树二分就行

    #include<bits/stdc++.h>
    #define LL long long
    LL in() {
    	char ch; LL x = 0, f = 1;
    	while(!isdigit(ch = getchar()))(ch == '-') && (f = -f);
    	for(x = ch ^ 48; isdigit(ch = getchar()); x = (x << 1) + (x << 3) + (ch ^ 48));
    	return x * f;
    }
    const int maxn = 1e5 + 10;
    struct LCT {
    protected:
    	struct node {
    		node *ch[2], *fa;
    		int col, num, rev;
    		node(int col = 0, int num = 0, int rev = 0): col(col), num(num), rev(rev) {
    			ch[0] = ch[1] = fa = NULL;
    		}
    		void trn() { std::swap(ch[0], ch[1]), rev ^= 1; }
    		bool ntr() { return fa && (fa->ch[0] == this || fa->ch[1] == this); }
    		bool isr() { return this == fa->ch[1]; }
    		void upd() {
    			num = col;
    			if(ch[0]) num |= ch[0]->num;
    			if(ch[1]) num |= ch[1]->num;
    		}
    		void dwn() {
    			if(!rev) return;
    			if(ch[0]) ch[0]->trn();
    			if(ch[1]) ch[1]->trn(); 
    			rev = 0;
    		}
    	}s[maxn], *t[maxn];
    	int top;
    	void rot(node *x) {
    		node *y = x->fa, *z = y->fa;
    		int k = x->isr(); node *w = x->ch[!k];
    		if(y->ntr()) z->ch[y->isr()] = x;
    		x->ch[!k] = y, y->ch[k] = w;
    		y->fa = x, x->fa = z;
    		if(w) w->fa = y;
    		y->upd(), x->upd();
    	}
    	void splay(node *o) {
    		t[top = 1] = o;
    		while(t[top]->ntr()) t[top + 1] = t[top]->fa, top++;
    		while(top) t[top--]->dwn();
    		while(o->ntr()) {
    			if(o->fa->ntr()) rot(o->fa->isr() ^ o->isr()? o : o->fa);
    			rot(o);
    		}
    	}
    	void access(node *x) {
    		for(node *y = NULL; x; x = (y = x)->fa)
    			splay(x), x->ch[1] = y, x->upd();
    	}
    	void makeroot(node *x) { access(x), splay(x), x->trn(); }
    	void link(node *x, node *y) { makeroot(x), x->fa = y; }
    	void change(node *x) {
    		access(x), splay(x);
    		x->col ^= 1;
    		x->upd();
    	}
    	node *dfs(node *o) {
    		if(o->ch[0]) {
    			if(o->ch[0]->num) return dfs(o->ch[0]);
    		}
    		if(o->col) return o;
    		return dfs(o->ch[1]);
    	}
    	int findans(node *x) {
    		makeroot(s + 1), access(x), splay(x);
    		if(!x->num) return -1;
    		return dfs(x) - s;
    	}
    public:
    	void ins(int n) { for(int i = 1; i < n; i++) link(s + in(), s + in()); }
    	void change(int x) { change(s + x); }
    	int query(int x) { return findans(s + x); }
    }v;
    int main() {
    	int n = in(), q = in();
    	v.ins(n);
    	while(q --> 0) {
    		if(in()) printf("%d
    ", v.query(in()));
    		else v.change(in());
    	}
    	return 0;
    }
    
  • 相关阅读:
    flutter添加启动图及设置启动时间
    flutter中通过循环渲染组件
    flutter学习资料汇总
    flutter中显现登录页面成功后跳转的方法
    flutter 常用视图组件
    mpvue学习笔记
    按钮放大动画效果
    一位练习时长两年半的内网渗透练习生
    Kali系统中20个超好用黑客渗透工具,你知道几个?
    渗透测试之三内网跳板
  • 原文地址:https://www.cnblogs.com/olinr/p/10263267.html
Copyright © 2020-2023  润新知