BZOJ1103: [POI2007]大都市meg

本文介绍了BZOJ1103大都市meg问题的解决思路,通过构建括号序列并利用树状数组来快速查询区间权值和,实现了动态更新节点状态的功能。

BZOJ1103: [POI2007]大都市meg

括号序·树状数组

题解:

首先求出括号序。如样例为1455422331
将进栈时打上标记1,出栈时打标记-1,这样已经退出的点的两个标记就会互相抵消
然后出栈序号与1号序号之间的权值和-1即为答案(排除1的影响)
修改时只要将对应标记变为0就可以了

Code:

#include <iostream>
#include <cstring>
#include <cstdio>
#define D(x) cout<<#x<<" = "<<x<<"  "
#define E cout<<endl
using namespace std;
const int N = 500005;

int n,m,tim, s[N],t[N];

struct Edge{
    int to,next;
} e[N*2];
int ec=0, head[N];
void add(int a,int b){
    ec++; e[ec].to=b; e[ec].next=head[a]; head[a]=ec;
}

struct BIT{
    int c[N*2], sz;
    inline int lowbit(int x){ return x&(-x); }
    void init(int _sz){ sz=_sz; memset(c,0,sizeof(c)); }
    void add(int x,int d){ while(x<=sz){ c[x]+=d; x+=lowbit(x); } }
    int sum(int x){ int ans=0; while(x>0){ ans+=c[x]; x-=lowbit(x); } return ans; }
} bit;

void dfs(int x,int f){
    s[x]=++tim;
    for(int i=head[x];i;i=e[i].next){
        int v=e[i].to;
        if(v==f) continue;
        dfs(v,x);
    }
    t[x]=++tim;
}

int main(){
    scanf("%d",&n);
    int a,b; char op[5];
    for(int i=1;i<n;i++){
        scanf("%d%d",&a,&b);
        add(a,b); add(b,a);
    }
    dfs(1,0); bit.init(tim);
    for(int i=2;i<=n;i++){
        bit.add(s[i],1); bit.add(t[i],-1);
    }
    scanf("%d",&m); m=m+n-1;
    for(int i=1;i<=m;i++){
        scanf("%s",op);
        if(op[0]=='A'){
            scanf("%d%d",&a,&b);
            bit.add(s[b],-1); bit.add(t[b],1);
        }
        else{
            scanf("%d",&a);
            printf("%d\n",bit.sum(s[a]));
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值