zoukankan      html  css  js  c++  java
  • [洛谷P3250][HNOI2016]网络

    题目大意:给定一棵树。有三种操作:

    1. $0;u;v;t:$在$u$到$v$的链上进行重要度为$t$的数据传输。
    2. $1;x:$结束第$x$个时刻的数据传输(保证合法)。
    3. $2;x:$询问不经过点$x$的数据传输中重要度最大的是多少(无解输出$-1$)。

    题解:可以发现一条路径对所有不在这条路径上的点有贡献,所以可以把这些区间给排除(树链剖分中的每一条链存下来),把其他位置加上一个数,可以给每个点维护一个大根堆。

    考虑删除一个数,可以再开一个大根堆,表示删除的数,若两个堆顶元素相同,就弹出。

    卡点:

    C++ Code:

    #include <algorithm>
    #include <cstdio>
    #include <queue>
    #include <iostream>
    #define maxn 100010
    inline int min(int a, int b) {return a < b ? a : b;}
    inline int max(int a, int b) {return a > b ? a : b;}
    
    int head[maxn], cnt;
    struct Edge {
    	int to, nxt;
    } e[maxn << 1];
    inline void add(int a, int b) {
    	e[++cnt] = (Edge) {b, head[a]}; head[a] = cnt;
    }
    
    int n, m;
    
    namespace SgT {
    	struct node {
    		std::priority_queue<int> A, D;
    		inline void push(int x) {A.push(x);}
    		inline void del(int x) {D.push(x);}
    		inline int top() {
    			while (!A.empty() && !D.empty() && A.top() == D.top()) A.pop(), D.pop();
    			return A.empty() ? -1 : A.top();
    		}
    	} V[maxn << 2];
    	int L, R, num, op;
    
    	void modify(int rt, int l, int r) {
    		if (L <= l && R >= r) {
    			if (op) V[rt].push(num);
    			else V[rt].del(num);
    			return ;
    		}
    		int mid = l + r >> 1;
    		if (L <= mid) modify(rt << 1, l, mid);
    		if (R > mid) modify(rt << 1 | 1, mid + 1, r);
    	}
    	void add(int __L, int __R, int __num) {
    		L = __L, R = __R, num = __num, op = 1;
    		modify(1, 1, n);
    	}
    	void del(int __L, int __R, int __num) {
    		L = __L, R = __R, num = __num, op = 0;
    		modify(1, 1, n);
    	}
    
    	int __ask(int rt, int l, int r) {
    		if (l == r) return V[rt].top();
    		int mid = l + r >> 1, ans = V[rt].top();
    		if (L <= mid) return max(ans, __ask(rt << 1, l, mid));
    		else return max(ans, __ask(rt << 1 | 1, mid + 1, r));
    	}
    	int ask(int __L) {
    		L = __L;
    		return __ask(1, 1, n);
    	}
    }
    using SgT::add;
    using SgT::del;
    using SgT::ask;
    
    int fa[maxn], dep[maxn], sz[maxn];
    int dfn[maxn], idx, top[maxn], son[maxn];
    void dfs1(int u) {
    	sz[u] = 1;
    	for (int i = head[u]; i; i = e[i].nxt) {
    		int v = e[i].to;
    		if (v != fa[u]) {
    			fa[v] = u;
    			dep[v] = dep[u] + 1;
    			dfs1(v);
    			sz[u] += sz[v];
    			if (!son[u] || sz[v] > sz[son[u]]) son[u] = v;
    		}
    	}
    }
    void dfs2(int u) {
    	dfn[u] = ++idx;
    	int v = son[u];
    	if (v) top[v] = top[u], dfs2(v);
    	for (int i = head[u]; i; i = e[i].nxt) {
    		v = e[i].to;
    		if (v != fa[u] && v != son[u]) {
    			top[v] = v;
    			dfs2(v);
    		}
    	}
    }
    
    struct Modify {
    	int u, v, x;
    } Mo[200010];
    
    struct List {
    	int l, r;
    	inline friend bool operator < (const List &lhs, const List &rhs) {
    		return lhs.l < rhs.l;
    	}
    } S[maxn];
    void modify(int u, int v, int x, int op = 1) {
    	int top = 0;
    	while (::top[u] != ::top[v]) {
    		if (dfn[::top[u]] < dfn[::top[v]]) std::swap(u, v);
    		S[top++] = (List) {dfn[::top[u]], dfn[u]};
    		u = fa[::top[u]];
    	}
    	if (dfn[u] > dfn[v]) std::swap(u, v);
    	S[top++] = (List) {dfn[u], dfn[v]};
    	std::sort(S, S + top);
    	int reach = 1;
    	for (int i = 0; i < top; reach = max(reach, S[i++].r + 1)) if (reach < S[i].l) {
    		if (op) add(reach, S[i].l - 1, x);
    		else del(reach, S[i].l - 1, x);
    	}
    	if (reach <= n) {
    		if (op) add(reach, n, x);
    		else del(reach, n, x);
    	}
    }
    int main() {
    	std::ios::sync_with_stdio(false), std::cin.tie(0), std::cout.tie(0);
    	std::cin >> n >> m;
    	for (int i = 1, a, b; i < n; i++) {
    		std::cin >> a >> b;
    		add(a, b);
    		add(b, a);
    	}
    	dfs1(1);
    	top[1] = 1;
    	dfs2(1);
    	for (int i = 1; i <= m; i++) {
    		int op, x, y, z;
    		std::cin >> op >> x;
    		switch (op) {
    			case 0:
    				std::cin >> y >> z;
    				Mo[i] = (Modify) {x, y, z};
    				modify(x, y, z);
    				break;
    			case 1:
    				modify(Mo[x].u, Mo[x].v, Mo[x].x, 0);
    				break;
    			case 2:
    				std::cout << ask(dfn[x]) << '
    ';
    				break;
    		}
    	}
    	return 0;
    }
    

      

  • 相关阅读:
    Java 利用 UUID 生成唯一性 ID 示例代码
    IntelliJ IDEA 使用前常用设置
    Tomcat 启动时项目报错 org.springframework.beans.factory.BeanCreationException
    MySQL-8.0.11 在 Windows10 上的安装
    Jwt在javaweb项目中的应用核心步骤解读
    nginx于tomcat项目整合(拆分静态文件)
    nginx提高加载静态文件速度
    Java构建网站多级菜单功能解决方案
    java手写的动态数组JimisunArray
    JavaIo编程基础复习
  • 原文地址:https://www.cnblogs.com/Memory-of-winter/p/10009580.html
Copyright © 2011-2022 走看看