HYSBZ - 4196 软件包管理器

HYSBZ - 4196 软件包管理器

树链剖分,用线段树进行区间维护,对已安装的软件标记为1,未安装的记为0,每次操作时,先查询,再更新。

#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <stack>
#include <set>
#include <map>
#include <string>
#include <math.h>
#include <stdlib.h>
#include <time.h>
#include <bitset>
#define INF 0x3f3f3f3f
#define eps 1e-6
#define PI 3.1415926
#define mod 1000000009
#define base 2333
using namespace std;
typedef long long LL;
const int maxn = 1e5 + 10;
const int maxx = 1e3 + 10;
inline void splay(int &v) {
    v=0;char c=0;int p=1;
    while(c<'0' || c >'9'){if(c=='-')p=-1;c=getchar();}
    while(c>='0' && c<='9'){v=(v<<3)+(v<<1)+c-'0';c=getchar();}
    v*=p;
}
int n, v, q, x, len, cnt, head[maxn], fa[maxn], son[maxn];
int siz[maxn], out[maxn], id[maxn], dep[maxn], top[maxn];
struct node {
    int to, next;
} e[maxn<<1];
struct Tree {
    int l, r, m;
    int lazy, val, ze, fr;
    void fun(int tmp) {
        lazy = tmp;
        val = (r-l+1)*tmp;
    }
} tr[maxn<<2];

void add(int from, int to) {
    e[len].to = to;
    e[len].next = head[from];
    head[from] = len++;
}

void dfs1(int u, int ff, int deep) {
    dep[u] = deep, fa[u] = ff;
    son[u] = -1, siz[u] = 1;
    for(int i = head[u]; ~i; i = e[i].next) {
        int v = e[i].to;
        if(v == ff) continue;
        dfs1(v, u, deep+1);
        siz[u] += siz[v];
        if(son[u] == -1 || siz[son[u]] < siz[v])
            son[u] = v;
    }
}
void dfs2(int u, int tp) {
    top[u] = tp;
    id[u] = ++cnt;
    if(son[u] != -1)  dfs2(son[u], tp);
    for(int i = head[u]; ~i; i = e[i].next) {
        int v = e[i].to;
        if(v == fa[u] || v == son[u]) continue;
        dfs2(v, v);
    }
    out[u] = cnt;
}

void PushUp(int id) {
    tr[id].val = tr[id<<1].val+tr[id<<1|1].val;
}

void PushDown(int id) {
    if(tr[id].lazy != -1) {
        tr[id<<1].fun(tr[id].lazy);
        tr[id<<1|1].fun(tr[id].lazy);
        tr[id].lazy = -1;
    }
}

void build(int id, int l, int r) {
    tr[id].l = l, tr[id].r = r, tr[id].lazy = -1;
    tr[id].m = (l+r)>>1;
    if(l == r)
        tr[id].val = 0;
    else {
        build(id<<1, l, tr[id].m);
        build(id<<1|1, tr[id].m+1, r);
        PushUp(id);
    }
}

void update(int id, int l, int r, int v) {
    if(l <= tr[id].l && r >= tr[id].r)
        tr[id].fun(v);
    else {
        PushDown(id);
        if(l <= tr[id].m) update(id<<1, l, r, v);
        if(r > tr[id].m) update(id<<1|1, l, r, v);
        PushUp(id);
    }
}

int query(int id, int l, int r, int op) {
    if(l <= tr[id].l && r >= tr[id].r) {
        if(op)  return (tr[id].r-tr[id].l+1)-tr[id].val;
        else  return tr[id].val;
    }
    else {
        PushDown(id);
        int sum = 0;
        if(l <= tr[id].m) sum += query(id<<1, l, r, op);
        if(r > tr[id].m) sum += query(id<<1|1, l, r, op);
        return sum;
    }
}

int Find(int u, int v) {
    int tp1 = top[u], tp2 = top[v];
    int ans = 0;
    while(tp1 != tp2) {
        if(dep[tp1] < dep[tp2]) {
            swap(tp1, tp2);
            swap(u, v);
        }
        ans += query(1, id[tp1], id[u], 1);
        update(1, id[tp1], id[u], 1);
        u = fa[tp1], tp1 = top[u];
    }
    if(dep[u] > dep[v]) swap(u, v);
    ans += query(1, id[u], id[v], 1);
    update(1, id[u], id[v], 1);
    return ans;
}

void solve() {
    splay(n);
    memset(head, -1, sizeof(head));
    len = cnt = 0;
    for(int i = 1; i < n; i++) {
        splay(v);
        add(i, v), add(v, i);
    }
    dfs1(0, -1, 1);
    dfs2(0, 0);
    build(1, 1, n);
    splay(q);
    char str[20];
    while(q--) {
        scanf("%s", str);
        splay(x);
        int ans = 0;
        if(str[0] == 'i') {
            ans = Find(0, x);
        }
        else  {
            ans = query(1, id[x], out[x], 0);
            update(1, id[x], out[x], 0);
        }
        printf("%d\n", ans);
    }
}

int main() {
    //srand(time(NULL));
    //freopen("kingdom.in","r",stdin);
    //freopen("kingdom.out","w",stdout);
    solve();
}



  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值