ZOJ 3686 A A Simple Tree Problem
2013-04-02 22:19
274 查看
开始想了一个错误的算法,对每个节点保存它的子树中的节点数目和其中为一的数目,操作某节点时向上更新其祖先的数据(log N),查询时直接输出。当时忽略了操作同时也需要更新后代的数据,这样的最坏复杂度是N,肯定是不行的。但直接交上去不是WA而是超时,由此猜想其中有类似链表的数据。
这个问题可以用线段树很好地解决,在对原树进行先序遍历的同时标上序号后,可以将任意子树转化为区间。序号介于某节点到它的任意后代间的点必为该节点的后代,在这种排序下即可建立线段树,将对子树的操作转化为对区间的操作。
这个问题可以用线段树很好地解决,在对原树进行先序遍历的同时标上序号后,可以将任意子树转化为区间。序号介于某节点到它的任意后代间的点必为该节点的后代,在这种排序下即可建立线段树,将对子树的操作转化为对区间的操作。
#include <stdio.h> #include <memory.h> #define N 100001 #define M 262144 #define Negate(x) label[x]=!label[x] #define Comple(a, b) sum[a]=b-sum[a] int right ; int first ; int next ; int num ; int sum[M]; bool label[M]; int a, b, ans; int n, m, cnt; void build(int index) { int i = first[index]; num[index] = ++ cnt; right[index] = cnt; while(i > 0) { build(i); if(right[i] > right[index]) right[index] = right[i]; i = next[i]; } } void update(int cur, int l, int r) { if(a<=l && b>=r) { Negate(cur); Comple(cur, r-l+1); } else { int mid = (l+r) >> 1; int x = cur<<1, y = x+1; if(label[cur] == true) { Negate(cur); Negate(x); Negate(y); Comple(x, mid-l+1); Comple(y, r-mid); } if(a <= mid) update(x, l, mid); if(b > mid) update(y, mid+1, r); sum[cur] = sum[x] + sum[y]; } } void query(int cur, int l, int r) { if (a<=l && b>=r) ans += sum[cur]; else { int mid = (l+r) >> 1; int x = cur<<1, y = x+1; if(label[cur] == true) { Negate(cur); Negate(x); Negate(y); Comple(x, mid-l+1); Comple(y, r-mid); } if(a <= mid) query(x, l, mid); if(b > mid) query(y, mid+1, r); sum[cur] = sum[x] + sum[y]; } } int main() { int node; while(scanf("%d%d", &n, &m) != EOF) { memset(first, 0, sizeof(first)); for(int i=2; i<=n; ++i) { scanf("%d", &node); next[i] = first[node]; first[node] = i; } cnt = 0; build(1); memset(label, false, sizeof(label)); memset(sum, 0, sizeof(sum)); char c[5]; for(int j=0; j<m; ++j) { scanf("%s", c); scanf("%d", &node); a = num[node]; b = right[node]; if(c[0] == 'q') { ans = 0; query(1, 1, n); printf("%d\n", ans); } else if(c[0] == 'o') update(1, 1, n); } printf("\n"); } return 0; }
相关文章推荐
- ZOJ 3686 : A Simple Tree Problem
- zoj3686 A Simple Tree Problem
- ZOJ 3686 A Simple Tree Problem (线段树)
- ZOJ_3686_A Simple Tree Problem(线段树成端更新)
- zoj 3686 A Simple Tree Problem
- ZOJ 3686 A Simple Tree Problem(树转线段树+线段树区间更新)
- zoj 3686 A Simple Tree Problem (经典,利用dfs序维护树)
- ZOJ 3686 A Simple Tree Problem
- zoj 3686 A Simple Tree Problem (线段树)
- ZOJ 3686 A Simple Tree Problem(线段树)
- ZOJ 3686 A Simple Tree Problem
- ZOJ-3686 A Simple Tree Problem 线段树
- ZOJ 3686 A Simple Tree Problem(线段树)
- ZOJ3686 A Simple Tree Problem
- zoj 3686 A Simple Tree Problem
- ZOJ 3686 A Simple Tree Problem
- ZOJ 3686 A Simple Tree Problem(线段树)
- zoj 3686 A Simple Tree Problem(dfs+线段树)
- ZOJ 3686 A Simple Tree Problem(将对树的操作转化成区间=>线段树)
- ZOJ 3686 A Simple Tree Problem (线段树)