【树链剖分】[BZOJ 4196]软件包管理器

来源:互联网 发布:上海优化公司hxwlkj 编辑:程序博客网 时间:2024/05/16 18:01

实际上就是个树链剖分,每次询问自己需要的到根节点中有多少开/开了,然后根据需要输出然后线段树Update的时候改一下改成每次更新全部,直接覆盖就行,每次扫描出来的一段肯定是上面半段开下面半段不开(分成两段)或者全部都处于开或者关,因为在链上任意一个处于开启状态那么之前的必须也处于开始状态。就是这样。

#include <cstdio>#include <algorithm>#include <cstring>//#include <conio.h>#include <iostream>using namespace std;const int MAXN = 100000;typedef long long LL;LL add[MAXN<<2], sum[MAXN<<2];int heavyson[MAXN+10], sons[MAXN+10], id[MAXN+10], last[MAXN+10], top[MAXN+10], idcnt;int depend[MAXN+10], fid[MAXN+10], n;struct node{    int v;    node *next;}Edges[MAXN*2+10], *ecnt=Edges, *adj[MAXN+10];void addedge(int u, int v){    ++ecnt;    ecnt->v = v;    ecnt->next = adj[u];    adj[u] = ecnt;}void PushUp(int rt){sum[rt] = sum[rt<<1] + sum[rt<<1|1];}void PushDown(int rt,int m){    if (add[rt] != 0) {        add[rt<<1] = add[rt<<1|1] = add[rt];        if(add[rt] == -1) add[rt] = 0;        sum[rt<<1] = add[rt] * (m - (m >> 1));        sum[rt<<1|1] = add[rt] * (m >> 1);        add[rt] = 0;    }}void update(int L,int R,int c,int l,int r,int rt) {    if (L <= l && r <= R) {        add[rt] = c;        sum[rt] = (c==-1?0:1) * (r - l + 1);        return ;    }    PushDown(rt , r - l + 1);    int mid = (l + r) >> 1;    if (L <= mid) update(L , R , c , l, mid, rt << 1);    if (mid < R) update(L , R , c , mid+1, r, (rt<<1)|1);    PushUp(rt);}LL query(int L,int R,int l,int r,int rt) {    if (L <= l && r <= R){        return sum[rt];    }    PushDown(rt , r - l + 1);    int mid = (l + r) >> 1;    LL ret = 0;    if (L <= mid) ret += query(L , R , l, mid, rt<<1);    if (mid < R) ret += query(L , R , mid+1, r, (rt<<1)|1);    return ret;}void dfs(int u){    sons[u] = 1; heavyson[u] = -1;    for(node *p=adj[u];p;p=p->next){        dfs(p->v);        sons[u] += sons[p->v];        if(heavyson[u] == -1 || sons[p->v] > sons[heavyson[u]])            heavyson[u] = p->v;    }}void dfs2(int u, int tp){    id[u] = ++idcnt; fid[idcnt] = u;    if(tp == -1) tp = top[u] = idcnt;    else top[u] = tp;    if(heavyson[u] > 0) dfs2(heavyson[u], tp);    for(node *p=adj[u];p;p=p->next) if(p->v != heavyson[u]){            dfs2(p->v, -1);        }    last[u] = idcnt;}int query_on(int u){    int tp = top[u], ret = 0, counter=0;    while(true){        counter += id[u]-tp+1;        if(tp == 1){            ret += query(1, id[u], 1, idcnt, 1);            update(top[u], id[u], 1, 1, idcnt, 1);            return counter - ret;        }        ret += query(top[u], id[u], 1, idcnt, 1);        update(top[u], id[u], 1, 1, idcnt, 1);        u = depend[fid[tp]]; tp = top[u];    }    return -1;}int query_off(int u){    int ret = query(id[u], last[u], 1, idcnt, 1);    update(id[u], last[u], -1, 1, idcnt, 1);    return ret;}char s[70];int main() {    //printf("%.3lf\n", (1.0 * sizeof(heavyson) + sizeof(sons) + sizeof(id) + sizeof(fid) + sizeof (top) + sizeof(Edges) + sizeof(depend) + sizeof(add) + sizeof(sum) )/1024.0/1024.0);    //getch();    scanf("%d", &n);    for(int i=1;i<n;i++){        scanf("%d", &depend[i]);        addedge(depend[i], i);    }    dfs(0);    dfs2(0,-1);    int q, i_s;    scanf("%d", &q);    for(int i=0;i<q;i++){        scanf("%s%d", s, &i_s);        if(s[0] == 'u') printf("%d\n", query_off(i_s));        else printf("%d\n", query_on(i_s));    }    return 0;}
0 0
原创粉丝点击