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;}
阅读全文
0 0
- DFS序 及 手动扩栈指令
- 手动扩栈
- 手动扩栈
- 手动扩栈
- 手动扩栈
- 手动扩栈
- 手动扩栈
- C++手动扩栈
- c++ 手动扩栈
- C++/G++ 手动扩栈
- G++/C++ 手动扩栈
- 黑科技 手动扩栈
- C++手动扩栈方法
- visual studio 手动扩栈
- 超强手动扩栈方法
- HDU 5274 Dylans loves tree(DFS序+线段树+LCA离线查询模板+手动扩大内存)
- 手动配置及开发Hibernate
- 手动配置及开发Struts
- 新的开始
- 聚集索引
- LeetCode【514】Freedom Trail
- HBuilder 制表符转换成空格
- 87 C语言条件编译详解
- DFS序 及 手动扩栈指令
- Ubuntu16.04安装32位支持库
- angular ui-router:简单的单页面嵌套路由的实现过程
- ZJCoj qwb与小数 ( 快速幂
- 88 C语言#error命令,阻止程序编译
- CSAPP:Attack Lab —— 缓冲区溢出攻击实验
- C++学习记录13--链表的简单理解
- 89 C语言预处理指令总结
- 线程GCD