洛谷P2146 [NOI2015]软件包管理器

https://www.luogu.org/problemnew/show/P2146 传送门

简单的树链剖分......维护下当前安装了多少个包......修改后查询下就行了......附上极其丑陋的代码......

#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;

const int N = 1e5 + 10;
int head[N], to[N], v[N], p;
void build(int a, int b) {    v[++ p] = b; to[p] = head[a]; head[a] = p; }

#define mid (l + r >> 1)
int tr[N << 2], lazy[N << 2];

void push_down(int c, int l, int r) {
    if( !lazy[c]) return ;
    lazy[c] --;
    tr[c << 1] = (mid - l + 1) * lazy[c]; tr[c << 1|1] = (r - mid) * lazy[c];
    lazy[c << 1] = lazy[c << 1|1] = lazy[c] + 1; lazy[c] = 0;
}

void change(int c, int l, int r, int L, int R, int o) {
    if( L <= l && R >= r) {
        tr[c] = (r - l + 1) * o; lazy[c] = o + 1; return ;
    }
    push_down(c, l, r);
    if( L <= mid) change(c << 1, l, mid, L, R, o);
    if( R > mid) change(c << 1|1, mid+1, r, L, R, o);
    tr[c] = tr[c << 1] + tr[c << 1|1];
}

int get_(int c, int l, int r, int L, int R) {
    if( l == L && R == r) return  tr[c];
    push_down(c, l, r);
    if( R <= mid) return get_(c << 1, l, mid, L, R);
    if( L > mid) return get_(c << 1|1, mid+1, r, L, R);
    return get_(c << 1, l, mid, L, mid) + get_(c << 1|1, mid+1, r, mid+1, R);
}

int son[N], si[N];
void search(int u) {
    si[u] = 1; son[u] = 0;
    for( int i = head[u]; ~i; i = to[i]) {
        search(v[i]), si[u] += si[v[i]];
        if( si[v[i]] > si[son[u]]) son[u] = v[i];
    }
}

int top[N], dfs[N], dfn[N], cnt;
void build_son(int u, int c) {
    top[u] = c; dfs[u] = ++cnt;
    if( son[u]) build_son(son[u], c);
    for( int i = head[u]; ~i; i = to[i]) 
        if( v[i] != son[u]) build_son(v[i], v[i]);
    dfn[u] = cnt;
}

int n, q, pre[N];
void query(int a) {
    int tcmp = tr[1];
    while( a) {
        change(1, 1, n, dfs[top[a]], dfs[a], 1); a = pre[top[a]];
    }printf("%d\n", tr[1] - tcmp);
}

char s[20];
int main() {
    scanf("%d", &n); memset(head, -1, sizeof(head)); p = -1;
    for( int i = 2; i <= n; i ++) scanf("%d", pre + i), pre[i] ++ ;
    for( int i = 1; i <= n; i ++) build(pre[i], i);
    
    search(1);build_son(1, 1);
    scanf("%d", &q);
    for( int i = 1, a; i <= q; i ++) {
        scanf("%s%d", s, &a); a ++;
        if( s[0] == 'i') query(a);
        else {
            int tcmp = tr[1]; change(1, 1, n, dfs[a], dfn[a], 0);
            printf("%d\n", tcmp - tr[1]);
        }
    }
}
View Code

猜你喜欢

转载自www.cnblogs.com/miecoku/p/9029292.html