Codeforces Round #200 (Div. 1) D - Water Tree 很经典而且很有趣的树 上dfs问题

来源:互联网 发布:ubuntu登陆后桌面假死 编辑:程序博客网 时间:2024/05/15 09:01

这道题疯狂wa了一大波,因为自己的线段树水平不够,更新 和 区间的理解还是大大的不够,所以一定要去多多学习。
题意:
给一颗树,有多次操作,有三种操作: 1. 把节点v 的所有 儿子节点(子树下的所有点)都充满水,2把节点v 的所有父亲节点的水都抽调。3.询问某个节点里面是否有水

.

一开始很年轻
感觉上 先跑出 dfs序,然后线段树维护一下节点flag值 就行了
好像感觉并不对,仔细想了想,如果我要把一个区间为: 2-4 这个节点 x清空,那么意味着x 有两个子节点1(3.3) 和2(4.4) 但是我不能把 1和2 清空啊。‘

那么我们在更新的时候修改一下姿势,和更新姿势没有关系,哪一种都是那样更新的
我们up 节点x的时候可以 吧区间弄为 L[x],L[x] ,这样就只会改变x 的祖先节点的flag值。

但是询问结果我们发现还是无法询问,因为区间不可能有两个啊,
那我们只能建两棵树了, 干脆区别对待
对于每一次的询问,我们都在两棵树上对同一个节点进行询问,看最后一次更新是1,还是2,由此便可得到是否有水

!!!!!!!仔细看看 线段树的更新 和询问 ,区间是很值得研究的 !!!!!!!

代码贴别人的,自己写的太丑了,就不拿出来了,蛤蛤

#include<iostream>#include<stdio.h>#include<string.h>#include<math.h>#include<algorithm>#include<stdlib.h>#include<queue>#include<stack>#include<map>#include<vector>#define mem(a) memset(a,0,sizeof(a))#define INF 0x7fffffff   //INT_MAX#define inf 0x3f3f3f3f   //const double PI = acos(-1.0);const double e = exp(1.0);template<class T> T gcd(T a, T b) { return b ? gcd(b, a % b) : a; }template<class T> T lcm(T a, T b) { return a / gcd(a, b) * b; }bool cmpbig(int a,int b){return a>b;}bool cmpsmall(int a,int b){return a<b;}using namespace std;#pragma comment(linker, "/STACK:1024000000,1024000000")const int N=500005;using namespace std;vector<int> E[N];int i, j, k, l, x, type, y, dfn[N], dfn2[N], tim, n, m;struct seg_tree {  int s[N * 4], sign[N * 4];  void cover(int p, int l, int r, int x, int y, int k) {    if (x <= l && y >= r) {      s[p] = sign[p] = k;//      printf("i=%d p=%d s=%d\n",i,p,s[p]);      return;    }    int mid = l + r >> 1;    if (x <= mid) cover(p << 1, l, mid, x, y, k);    if (y > mid) cover((p << 1) + 1, mid + 1, r, x, y, k);    s[p] = max(s[p << 1], s[(p << 1) + 1]);//    printf("i=%d p=%d s=%d\n",i,p,s[p]);  }  int calc(int p, int l, int r, int x, int y) {    if (x <= l && y >= r) return s[p];    int mid = l + r >> 1, res = 0;    if (x <= mid) res = max(res, calc(p << 1, l, mid, x, y));    if (y > mid) res = max(res, calc((p << 1) + 1, mid + 1, r, x, y));    return max(sign[p], res);  }} T1, T2;void dfs(int x, int ff) {  dfn[x] = ++tim;  for (int i = E[x].size() - 1; i >= 0; --i)    if (E[x][i] != ff) dfs(E[x][i], x);  dfn2[x] = tim;}int main() {  scanf("%d", &n);  for (i = 1; i < n; ++i) {    scanf("%d%d", &x, &y);    E[x].push_back(y);    E[y].push_back(x);  }  dfs(1, 0);  scanf("%d", &m);  for (i = 1; i <= m; ++i) {    scanf("%d%d", &type, &x);    if (type == 1) {      T1.cover(1, 1, n, dfn[x], dfn2[x], i);    }    if (type == 2) {      T2.cover(1, 1, n, dfn[x], dfn[x], i);    }    if (type == 3) {      int v1 = T1.calc(1, 1, n, dfn[x], dfn[x]);      int v2 = T2.calc(1, 1, n, dfn[x], dfn2[x]);//      printf("v=  %d %d\n",v1,v2);      if (v2 >= v1)        puts("0");      else        puts("1");    }  }}
0 0
原创粉丝点击