zoukankan      html  css  js  c++  java
  • [CF1083C]Max Mex

    题目大意:有一棵$n(nleqslant2 imes10^5)$个点的树,每个点有点权,所有的点权构成了$0sim n-1$的排列。$q(qleqslant2 imes10^5)$次操作,操作有两种:

    1. $1;x;y:$交换$x$和$y$的点权
    2. $2:$询问$maxlimits_{x,yin V}{mex(x o y)}$

    题解:这个明显具有可二分性(然后我考场上写了一个虚树判链的,复杂度爆炸+没用)。翻看题解知道这道题可以用线段树来维护区间点是否在一条链上,在区间合并的时候枚举一下在两个区间的四个端点中是哪两个端点为大区间的端点,用$LCA$以及$dfn$序判断一下即可。

    在最开始判一下树的形态是一条链的情况

    卡点:

    C++ Code:

    #include <algorithm>
    #include <cctype>
    #include <cstdio>
    namespace __IO {
    	int ch;
    	inline int read() {
    		static int x;
    		while (isspace(ch = getchar())) ; x = ch & 15;
    		while (isdigit(ch = getchar())) x = x * 10 + (ch & 15);
    		return x;
    	}
    }
    using __IO::read;
    
    #define maxn 200010
    int head[maxn], cnt;
    struct Edge {
    	int to, nxt;
    } e[maxn];
    inline void addedge(int a, int b) {
    	e[++cnt] = (Edge) { b, head[a] }; head[a] = cnt;
    }
    
    int fa[maxn], sz[maxn], dep[maxn];
    int top[maxn], dfn[maxn], idx;
    int find(int x) { return x == top[x] ? x : (top[x] = find(top[x])); }
    void dfs(int u) {
    	int son = 0;
    	dfn[u] = ++idx, sz[u] = 1;
    	for (int i = head[u], v; i; i = e[i].nxt) {
    		v = e[i].to;
    		dep[v] = dep[u] + 1;
    		dfs(v), sz[u] += sz[v];
    		if (sz[v] > sz[son]) son = v;
    	}
    	if (son) top[son] = u;
    }
    inline int LCA(int x, int y) {
    	while (top[x] != top[y]) {
    		if (dep[top[x]] > dep[top[y]]) x = fa[top[x]];
    		else y = fa[top[y]];
    	}
    	return dep[x] < dep[y] ? x : y;
    }
    
    int n, m, w[maxn], ret[maxn];
    
    inline bool in_sub(int x, int y) {
    	return (dfn[x] >= dfn[y]) && (dfn[x] < dfn[y] + sz[y]);
    }
    inline bool in_line(int x, int y, int z) {
    	static int lca; lca = LCA(x, y);
    	return in_sub(z, lca) && (in_sub(x, z) || in_sub(y, z));
    }
    inline bool in_line(int x, int y, int l, int r) {
    	return in_line(x, y, l) && in_line(x, y, r);
    }
    
    struct node {
    	bool line;
    	int l, r;
    	inline node() { }
    	inline node(int __l) : line(true), l(__l), r(__l) { }
    	inline node(int __l, int __r) : line(true), l(__l), r(__r) { }
    	inline node(bool __line, int __l, int __r) : line(__line), l(__l), r(__r) { }
    	static inline node NS() { return node(0, -1, -1); }
    	inline node operator + (const node &rhs) const {
    		if (!l || !r) return rhs;
    		if (!line || !rhs.line) return NS();
    		const int x = rhs.l, y = rhs.r;
    		if (in_line(l, r, x, y)) return node(l, r);
    		if (in_line(l, x, r, y)) return node(l, x);
    		if (in_line(l, y, x, r)) return node(l, y);
    		if (in_line(r, x, l, y)) return node(r, x);
    		if (in_line(r, y, l, x)) return node(r, y);
    		if (in_line(x, y, l, r)) return node(x, y);
    		return NS();
    	}
    } I(0, 0, 0);
    
    namespace SgT {
    	node V[maxn << 2];
    	void build(const int rt, const int l, const int r) {
    		if (l == r) {
    			V[rt] = node(ret[l]);
    			return ;
    		}
    		const int mid = l + r >> 1;
    		build(rt << 1, l, mid), build(rt << 1 | 1, mid + 1, r);
    		V[rt] = V[rt << 1] + V[rt << 1 | 1];
    	}
    
    	int pos;
    	void __modify(const int rt, const int l, const int r) {
    		if (l == r) {
    			V[rt] = node(ret[l]);
    			return ;
    		}
    		const int mid = l + r >> 1;
    		if (pos <= mid) __modify(rt << 1, l, mid);
    		else __modify(rt << 1 | 1, mid + 1, r);
    		V[rt] = V[rt << 1] + V[rt << 1 | 1];
    	}
    	void modify(const int __pos) {
    		pos = __pos;
    		__modify(1, 0, n - 1);
    	}
    
    	node now;
    	int res;
    	void __query(int rt, int l, int r) {
    		if (l == r) {
    			res = l;
    			return ;
    		}
    		node tmp = now + V[rt << 1];
    		const int mid = l + r >> 1;
    		if (tmp.line) {
    			now = tmp;
    			__query(rt << 1 | 1, mid + 1, r);
    		} else __query(rt << 1, l, mid);
    	}
    	int query() {
    		now = I, res = 1;
    		__query(1, 0, n - 1);
    		return res;
    	}
    }
    
    int ind[maxn];
    bool is_line = true;
    int main() {
    	n = read();
    	for (int i = 1; i <= n; ++i) {
    		w[i] = read();
    		ret[w[i]] = top[i] = i;
    	}
    	for (int i = 2; i <= n; ++i) {
    		fa[i] = read();
    		addedge(fa[i], i);
    		++ind[fa[i]], ++ind[i];
    		if (ind[fa[i]] > 2 || ind[i] > 2) is_line = false;
    	}
    	dfs(1);
    	for (int i = 1; i <= n; ++i) find(i);
    	SgT::build(1, 0, n - 1);
    
    	m = read();
    	while (m --> 0) {
    		static int op, x, y;
    		op = read();
    		if (op == 1) {
    			x = read(), y = read();
    			std::swap(ret[w[x]], ret[w[y]]), std::swap(w[x], w[y]);
    			if (!is_line) SgT::modify(w[x]), SgT::modify(w[y]);
    		} else printf("%d
    ", is_line ? n : SgT::query());
    	}
    	return 0;
    }
    

      

  • 相关阅读:
    分布式系统与机器学习相关笔记
    天坑:OpenGL制作游戏引擎备忘记录
    2016ACM-ICPC 大连站、青岛站、China-Final 赛后总结(无删版)by wanglangzhe || wmzksana
    CF 609E, 树链剖分
    CF 609F,线段树上二分 + set维护
    CF 540E, 树状数组
    hdu 5726, 2016多校1
    hdu5836, 2016CCPC网络赛
    SYSU-10,URAL 1675,容斥原理
    动态规划基础篇 from 51nod
  • 原文地址:https://www.cnblogs.com/Memory-of-winter/p/10346355.html
Copyright © 2011-2022 走看看