DFS序 及 手动扩栈指令

来源:互联网 发布:网站 seo 编辑:程序博客网 时间:2024/06/06 11:44

概念

DFS序是转树型结构为线型结构的经典方法。


具体实现网上优秀博客很多,就不赘述了….
因为涉及DFS,同时此类题普遍节点的规模都在1e5以上,而HDOJ好像是基于Windows的服务器,很容易爆栈,故我们需要添加一个手动扩栈指令,并用C++提交。

#pragma comment(linker, “/STACK:1024000000,1024000000”)


经典题

HDOJ 3887

题意很简单,但思路却困了我很久,一直纠结于如何解决不同子树相互影响的问题。
但其实由DFS序的性质,假设存在某一个节点X

当搜索到X时,之前搜索到的节点一定不属于X的子树,此时我们用树状数组维护此前出现过的节点的标号,然后查询小于X的标号的节点数量 num_1

当搜索完X的子节点后,树状数组里面会包含X的succeeding nodes即后继节点的信息,再查询小于X的标号的节点数量num_2

然后易得: F[X] = num_2 - num_1

代码:

#pragma comment(linker, "/STACK:1024000000,1024000000")#include<cstdio>#include<cstdlib>#include<cstring>#include<algorithm>#include<cmath>#include<cctype>#include<queue>using namespace std;typedef long long ll;#define lson rt<<1#define rson rt<<1|1const int A = 1e5 + 10;class BIT{public:    int c[A];    void init(){        memset(c,0,sizeof(c));    }    void update(int pos,int val){        for(int i=pos ;i<A ;i+=(i&(-i))) c[i]+=val;    }    int query(int pos){        int res =0;        for(int i=pos ;i>0 ;i-=(i&(-i))) res+=c[i];        return res;    }}bit;class P{public:    int v,next;}G[A<<1];int tot,Rank,head[A],Ans[A];inline void init(){    memset(head,-1,sizeof(head));    tot = Rank = 0;    bit.init();}inline void add(int u,int v){    G[tot].v = v;    G[tot].next = head[u];    head[u] = tot++;}void dfs(int u,int pre){    int num1 = bit.query(u);    for(int i=head[u] ;i!=-1 ;i=G[i].next){        int v = G[i].v;        if(v == pre) continue;        dfs(v,u);    }    int num2 = bit.query(u);    Ans[u] = num2 - num1;    bit.update(u,1);}int main(){    int n,p;    while(~scanf("%d%d",&n,&p)){        if(!n && !p) break;        init();        for(int i=1 ;i<n ;i++){            int u,v;            scanf("%d%d",&u,&v);            add(u,v);add(v,u);        }        dfs(p,-1);        for(int i=1 ;i<=n ;i++){            printf("%d%c",Ans[i],(i==n?'\n':' '));        }    }    return 0;}

HDOJ 5692

此题因为写错了一个小细节WA了十几发qwq

此题是DFS序结合线段树的经典题,即当线段树维护的不再是一个线性结构而变成树形结构时,我们需要DFS序来进行转换。

理解清DFS序的概念此题便很简单了

#pragma comment(linker, "/STACK:1024000000,1024000000")#include <iostream>#include<iomanip>#include <cstdio>#include <cstdlib>#include<cstring>#include <string>#include <algorithm>#include <cmath>#include <cctype>#include<queue>#include<map>#include<stack>using namespace std;typedef long long ll;#define lson rt<<1#define rson rt<<1|1const ll INF = 1e18;const int A = 1e5 + 10;class P{public:    int l,r;    ll Max,mark;}Tree[A<<2];class Node{public:    int v,next;}G[A<<1];int in[A],out[A],head[A],ID[A];int tot,Rank;int n,m;ll dis[A],a[A];void init(){    tot = Rank = 0;    memset(head,-1,sizeof(head));}void add(int u,int v){    G[tot].v = v;    G[tot].next = head[u];    head[u] = tot++;}void dfs(int u,int pre){    in[u] = ++Rank;    ID[Rank] = u;    for(int i=head[u] ;i!=-1 ;i=G[i].next){        int v = G[i].v;        if(v == pre) continue;        dis[v] = dis[u] + a[v];        //printf("dis[%d] = %d\n",v,dis[v]);        dfs(v,u);    }    out[u] = Rank;}void push_up(int rt){    Tree[rt].Max = max(Tree[lson].Max,Tree[rson].Max);}void push_down(int rt){    if(Tree[rt].mark){        Tree[lson].mark += Tree[rt].mark;        Tree[rson].mark += Tree[rt].mark;        Tree[lson].Max += Tree[rt].mark;        Tree[rson].Max += Tree[rt].mark;        Tree[rt].mark = 0;    }}void build_Tree(int rt,int l,int r){    Tree[rt].l = l,Tree[rt].r = r;    Tree[rt].mark = 0;    if(l == r){        Tree[rt].Max = dis[ID[l]];        return;    }    int mid = (l+r)>>1;    build_Tree(lson,l,mid);    build_Tree(rson,mid+1,r);    push_up(rt);}void update(int rt,int st,int ed,ll c){    int l = Tree[rt].l,r = Tree[rt].r;    if(st<=l && r<=ed){        Tree[rt].Max += c;        Tree[rt].mark += c;        return;    }    push_down(rt);    int mid = (l+r)>>1;    if(st<=mid) update(lson,st,ed,c);    if(ed> mid) update(rson,st,ed,c);    push_up(rt);}ll query(int rt,int st,int ed){    int l = Tree[rt].l,r = Tree[rt].r;    if(st<=l && r<=ed){        return Tree[rt].Max;    }    push_down(rt);    int mid = (l+r)>>1;    ll res = -INF;    if(st<=mid) res = max(res,query(lson,st,ed));    if(ed> mid) res = max(res,query(rson,st,ed));    return res;}int main(){    //freopen("input","r",stdin);    int T,_=1;    scanf("%d",&T);    while(T--){        printf("Case #%d:\n",_++);        init();        scanf("%d%d",&n,&m);        for(int i=0 ;i<n-1 ;i++){            int u,v;            scanf("%d%d",&u,&v);            add(u,v);add(v,u);        }        for(int i=0 ;i<n ;i++) scanf("%I64d",&a[i]);        dis[0] = a[0];        dfs(0,-1);        build_Tree(1,1,n);        int op;        while(m--){            scanf("%d",&op);            if(op == 1){                int x;                scanf("%d",&x);                printf("%I64d\n",query(1,in[x],out[x]));            }            else{                int x;                ll y;                scanf("%d%I64d",&x,&y);                update(1,in[x],out[x],y-a[x]);                a[x] = y;            }        }    }    return 0;}