zoukankan      html  css  js  c++  java
  • 洛谷P2146 [NOI2015]软件包管理器

    题目链接

    走这里

    题目分析

    对不起我就来水个博客
    好像这段时间一直很颓,但是什么事情都不干又良心不安,所以就来颓个树剖。
    说正事。
    最开始做这个题的时候sb了一下,因为虽然可以当做染色染0和1,不知道怎么统计状态变化的软件包的数量,后来发现我们在线段树上维护的(sum)的变化值其实就是这段区间状态变化的软件包的数量,然后我们可以偷个懒不用区间查询,直接输出线段树根节点的(sum)变化量即可。

    代码

    贴一个极致压行的80行代码,第一次10min以内过树剖题,有点感动。

    #include <bits/stdc++.h>
    #define ls(p) p << 1
    #define rs(p) p << 1 | 1 
    #define N (200000 + 10)
    using namespace std;
    inline int read() {
    	int cnt = 0, f = 1; char c = getchar();
    	while (!isdigit(c)) {if (c == '-') f = -f; c = getchar();}
    	while (isdigit(c)) {cnt = (cnt << 3) + (cnt << 1) + c - '0'; c = getchar();}
    	return cnt * f;
    }
    int nxt[N], to[N], first[N], tot, n, q, x;
    void Add(int x, int y) {nxt[++tot] = first[x], first[x] = tot, to[tot] = y;}
    int dep[N], siz[N], father[N], son[N], id[N], top[N], idx;
    char ope[20];
    void dfs_(int x, int fa) {
    	dep[x] = dep[fa] + 1, siz[x] = 1, father[x] = fa;
    	for (register int i = first[x]; i; i = nxt[i]) {
    		int v = to[i];
    		if (v == fa) continue;
    		dfs_(v, x);
    		siz[x] += siz[v];
    		if (siz[son[x]] < siz[v]) son[x] = v;
    	}
    }
    void dfs__(int x, int tp) {
    	top[x] = tp, id[x] = ++idx;
    	if (son[x]) dfs__(son[x], tp);
    	for (register int i = first[x]; i; i = nxt[i]) {
    		int v = to[i];
    		if (!id[v]) dfs__(v, v);
    	}
    }
    struct segmentree {
    	int l, r, sum, tag;
    	#define l(p) tree[p].l
    	#define r(p) tree[p].r
    	#define sum(p) tree[p].sum
    	#define tag(p) tree[p].tag 
    }tree[N << 2];
    void push_up(int p) {sum(p) = sum(ls(p)) + sum(rs(p));}
    void push_rev(int p, int k) {sum(p) = (k ? (r(p) - l(p) + 1) : 0), tag(p) = k;}
    void push_down(int p) {
    	if (tag(p) >= 0) push_rev(ls(p), tag(p)), push_rev(rs(p), tag(p)), tag(p) = -1;
    }
    void build(int p, int l, int r) {
    	l(p) = l, r(p) = r;
    	if (l == r) {tag(p) = -1; return;}
    	int mid = (l + r) >> 1;
    	build (ls(p), l, mid), build (rs(p), mid + 1, r);
    	push_up(p);
    }
    void modify(int p, int l, int r, int d) {
    	if (l <= l(p) && r >= r(p)) { push_rev(p, d); return;}
    	push_down(p);
    	int mid = (l(p) + r(p)) >> 1;
    	if (l <= mid) modify (ls(p), l, r, d);
    	if (r > mid) modify(rs(p), l, r, d);
    	push_up(p); 
    }
    void Modify(int u, int v, int d) {
    	while (top[u] != top[v]) {
    		if (dep[top[u]] < dep[top[v]]) swap(u, v);
    		modify(1, id[top[u]], id[u], d);
    		u = father[top[u]];
    	}
    	dep[u] < dep[v] ? modify(1, id[u], id[v], d) : modify(1, id[v], id[u], d);
    }
    signed main() {
    	n = read(); 
    	for (register int i = 2; i <= n; ++i) x = read() + 1, Add(x, i), Add(i, x);
    	dfs_(1, 0), dfs__(1, 1), build (1, 1, n);
    	q = read();
    	for (register int i = 1; i <= q; i++) {
    		scanf("%s", ope + 1); int ans = sum(1);
    		x = read() + 1, ope[1] == 'i' ? Modify(x, 1, 1) : modify(1, id[x], id[x] + siz[x] - 1, 0); 
    		printf("%d
    ", abs(ans - sum(1)));
    	}
    	return 0;
    }
    
  • 相关阅读:
    java-数组
    编程练习
    java-循环语句
    java-条件语句if&switch
    JAVA-运算符
    JAVA-常量
    springAOP源码分析之篇一:配置文件的解析
    spring IOC容器的扩展
    spring IOC之篇六 bean的加载---bean的创建
    spring IOC之篇五 bean的加载--缓存中获取
  • 原文地址:https://www.cnblogs.com/kma093/p/11289837.html
Copyright © 2011-2022 走看看