BZOJ-1103: [POI2007]大都市meg 题解

题目:****http://www.lydsy.com/JudgeOnline/problem.php?id=1103

先将该树处理成DFS序列,然后用树状数组维护,在首次进入的点出+1,最后退出的点处-1,然后查询时该点的前缀和-1即为答案。每次该边时就将对应的点进入和退出两个位置改成0就好了。总体的说,这是一道有思考性的树状数组题目。

代码:

#include 

#include 

#include 

#include 

#include 

  

using namespace std;

  

#define MAXN 250001

#define lowbit(x)(((~(x))+1)&x)

  

int n,m;

  

struct edge {

    int t;

    edge *next;

    edge (){

        next=NULL;

    }

} *head[MAXN];

  

int dfs[MAXN*2];

int first[MAXN],last[MAXN];

int t[MAXN*2];

int IN[MAXN];

  

void INSERT(int s,int t){

    edge *p=new(edge);

    p->t=t;

    p->next=head[s];

    head[s]=p;

    p=new(edge);

    p->t=s;

    p->next=head[t];

    head[t]=p;

}

  

struct node {

    int v;

    edge *p;

    bool flag;

    node (int _v,edge *_p,bool _flag):v(_v),p(_p),flag(_flag){

    }

};

  

stacks;

  

int N=0;

  

bool flag[MAXN];

  

void DFS(){

    memset(flag,true,sizeof(flag));

    while (!s.empty()){

        s.pop();

    }

    s.push(node(1,head[1],true));

    while (!s.empty()){

        node i=s.top();

        flag[i.v]=false;

        s.pop();

        if (i.flag){

            dfs[++N]=i.v;

            first[i.v]=N;

            i.flag=false;

        }

        if (i.p==NULL){

            dfs[++N]=i.v;

            last[i.v]=N;

        } else {

            s.push(node(i.v,i.p->next,false));

            if (!flag[i.p->t]){

                continue;

            }

            IN[i.p->t]=i.v;

            s.push(node(i.p->t,head[i.p->t],true));

        }

    }

}

  

void Add(int x,int y){

    while (x<=N) t[x]+=y,x+=lowbit(x);

}

  

int Suffsum(int x){

    int rec=0;

    while (x) rec+=t[x],x-=lowbit(x);

    return rec;

}

  

int main(){

    scanf("%d",&n);

    for (int i=0;i++

你可能感兴趣的:(BZOJ-1103: [POI2007]大都市meg 题解)