Codeforces Round #200 (Div. 1)D. Water Tree 【dfs序+线段树】
2016-05-02 13:43
429 查看
方法1
把树按照dfs序展开,用线段树维护子树和,设0表示empty,1表示filled
操作1:若子树v存在0节点,则把v的父亲【in[fa],out[fa]】更新成0。然后把【in[v],out[v]】更新成1
操作2:把节点v更新成0
操作3:询问【st[v],ed[v]】区间内是否有0节点,没有则表示1
方法2
用两棵线段树维护,对于操作1,第一棵线段树区间加1,对于操作二,变空的点加1,对于操作3,查询第一第二课的区间大小并比较
把树按照dfs序展开,用线段树维护子树和,设0表示empty,1表示filled
操作1:若子树v存在0节点,则把v的父亲【in[fa],out[fa]】更新成0。然后把【in[v],out[v]】更新成1
操作2:把节点v更新成0
操作3:询问【st[v],ed[v]】区间内是否有0节点,没有则表示1
方法2
用两棵线段树维护,对于操作1,第一棵线段树区间加1,对于操作二,变空的点加1,对于操作3,查询第一第二课的区间大小并比较
#include<bits/stdc++.h> using namespace std; const int N=500000+10; vector<int>v ; int in ,out ,f ,vis ,n,tot,ans; void dfs(int x,int fa) { vis[x]=1; in[x]=++tot; f[x]=fa; for(int i=0; i<v[x].size(); i++) { if(vis[v[x][i]]==0) { dfs(v[x][i],x); } } out[x]=tot; } struct Tree { int l,r,f,sum; }tree[4*N]; void build(int o,int l,int r) { tree[o].l=l; tree[o].r=r; tree[o].f=-1; tree[o].sum=0; if(l!=r) { int mid=(l+r)/2; build(o*2,l,mid); build(o*2+1,mid+1,r); } } void pushdown(int o) { if(tree[o].f!=-1) { tree[o*2].f=tree[o*2+1].f=tree[o].f; tree[o*2].sum=(tree[o*2].r-tree[o*2].l+1)*tree[o].f; tree[o*2+1].sum=(tree[o*2+1].r-tree[o*2+1].l+1)*tree[o].f; tree[o].f=-1; } } void update(int o,int l,int r,int val) { if(l<=tree[o].l&&tree[o].r<=r) { tree[o].f=val; tree[o].sum=val*(tree[o].r-tree[o].l+1); } else { pushdown(o); int mid=(tree[o].l+tree[o].r)/2; if(l<=mid) update(o*2,l,r,val); if(r>mid) update(o*2+1,l,r,val); tree[o].sum=tree[o*2].sum+tree[o*2+1].sum; } } int query(int o,int l,int r) { if(tree[o].f!=-1) { int maxl=max(l,tree[o].l); int minr=min(r,tree[o].r); return tree[o].f*(minr-maxl+1); } if(l<=tree[o].l&&tree[o].r<=r) { return tree[o].sum; } else { int ret=0; //pushdown(o); int mid=(tree[o].l+tree[o].r)/2; if(l<=mid) ret+=query(o*2,l,r); if(r>mid) ret+=query(o*2+1,l,r); return ret; } } int main() { int a,b,q,ci,vi; scanf("%d",&n); for(int i=1; i<=n; i++) v[i].clear(); for(int i=0; i<n-1; i++) { scanf("%d%d",&a,&b); v[a].push_back(b); v[b].push_back(a); } memset(vis,0,sizeof(vis)); tot=0; dfs(1,0); build(1,1,tot); scanf("%d",&q); for(int i=0; i<q; i++) { scanf("%d%d",&ci,&vi); if(ci==1) { if(query(1,in[vi],out[vi])<(out[vi]-in[vi]+1)&&f[vi]!=0) update(1,in[f[vi]],in[f[vi]],0); update(1,in[vi],out[vi],1); } else if(ci==2) { update(1,in[vi],in[vi],0); } else if(ci==3) { if(query(1,in[vi],out[vi])<(out[vi]-in[vi]+1)) puts("0"); else puts("1"); } } return 0; }
相关文章推荐
- java数组排序,二分查找
- 一种解决h5页面背景音乐不能自动播放的方案
- C语言有参函数调用时参数间数据传递问题
- am335x i2c分析
- Ubuntu 16.04如何安装Cinnamon 3.0
- 周末来一发之五一周赛
- java concurrent 之 SynchronousQueue
- Leetcode #345. Reverse Vowels of a String 逆转元音字母 解题报告
- Powershell集成OPENSSL客户端
- Linux PS命令详解
- Ubuntu下Zotero及Docear的安装、插件配置、联合使用
- 进程同步(三)—— 信号
- Linux驱动开发之 三 (那些必须要了解的硬件知识 之 存储器篇)
- Linux netstat命令详解
- java中几种复制数组的方法比较
- 百度高级搜索技巧
- redis-list(列表)
- Linux开机自启配置
- sublime text快捷键
- Java本地文件操作(一)文件的创建、删除、重命名