码迷,mamicode.com
首页 > 其他好文 > 详细

SPOJ QTREE Query on a tree

时间:2016-11-04 20:39:49      阅读:226      评论:0      收藏:0      [点我收藏+]

标签:i++   操作   code   ons   ++   深度   str   ack   双向   

题意:
给一颗n个点的树,有两种操作
CHANGE i ti : 把第i条边的权变为ti
QUERY a b : 问点a 到 点b 之间的边的最大权

思路:
树剖处理边权。
由于是边,所以只需要把边权处理到子节点上即可(查询的时候从节点2开始查询,或者把0处理成负无穷)

 

具体见代码:

  1 const int maxn = 10000 + 10;
  2 const int maxnode = maxn * 4;
  3 
  4 //线段树部分
  5 int set_value, qL, qR;
  6 int maxv[maxnode];
  7 
  8 void update(int o, int L, int R) 
  9 {
 10     if (qL <= L && R <= qR) 
 11     {
 12         maxv[o] = set_value;
 13         return;
 14     }
 15     int M = L + (R - L) / 2;
 16     if (qL <= M) update(lson);
 17     if (qR > M) update(rson);
 18     maxv[o] = max(maxv[o*2], maxv[o*2+1]);
 19 }
 20 
 21 int query(int o, int L, int R) {
 22     if (qL <= L && R <= qR) 
 23     {
 24         return maxv[o];
 25     }
 26     int M = L + (R - L) / 2;
 27     int ret = -INF;
 28     if (qL <= M) ret = max(ret, query(lson));
 29     if (qR > M) ret = max(ret, query(rson));
 30     return ret;
 31 }
 32 
 33 //树链剖分部分:
 34 //
 35 //u为连接的点,w为边权
 36 struct Edge { int u, v, w; };
 37 vector<int> G[maxn];
 38 vector<Edge> e;
 39 //往往是双向边
 40 void add_edge(int u, int v, int w)
 41 {
 42     e.push_back((Edge){u, v, w});
 43     G[u].push_back(v);
 44     G[v].push_back(u);
 45 }
 46 
 47 struct Node
 48 {
 49     int size, dep, son, top, fa, ti;
 50     //依次表示第i个节点的:
 51     //子节点数量,深度,所在链的顶端,重儿子,dfs序
 52 } t[maxn];
 53 
 54 int dfs_clock;//DFS时间序列
 55 
 56 void dfs1(int u, int pa, int depth)//第一次DFS,得到size,dep,fa以及son的数据
 57 {
 58     t[u].son = 0; //重儿子,为0表示没有重儿子
 59     t[u].size = 1;    //节点数量
 60     t[u].dep = depth;
 61     t[u].fa = pa;
 62     for (int i = 0; i != G[u].size(); ++ i)
 63     {
 64         int v = G[u][i];
 65         if (v == pa) continue;
 66         dfs1(v, u, depth + 1);
 67         t[u].size += t[v].size;
 68         if (t[v].size > t[t[u].son].size) t[u].son = v;
 69     }
 70 }
 71 
 72 void dfs2(int u, int pa)    // 得到时间戳等数据,u为当前节点,pa为父链顶端节点
 73 {
 74     t[u].ti = ++ dfs_clock; //u这个节点的时间戳是dfs_clock,dfs_clock下标是从1开始的,没有0!
 75     t[u].top = pa;        //top是u所在链的顶端
 76     if (t[u].son != 0) dfs2(t[u].son, t[u].top);    //如果节点有重儿子,那么依旧是以pa为链顶端的一条链
 77     for (int i = 0; i != G[u].size(); ++ i)
 78     {
 79         int v = G[u][i];
 80         if (v == t[u].son || v == t[u].fa)    continue;//重儿子或者父节点,则跳过
 81         dfs2(v, v);//新的一条链
 82     }
 83 }
 84 
 85 int n;
 86 int lca(int x, int y)//更新x到y的之间所有的区间
 87 {
 88     int ret = -INF;
 89     while (t[x].top != t[y].top)
 90     {
 91         if (t[t[x].top].dep < t[t[y].top].dep) swap(x,y); //x深 y浅
 92         qL=t[t[x].top].ti;
 93         qR=t[x].ti;
 94         ret = max(ret, query(1, 2, n));
 95         x = t[t[x].top].fa;
 96     }
 97     if (t[x].dep > t[y].dep) swap(x, y);//x是上面一些的节点
 98     if (x != y)
 99     {
100         qL = t[x].ti + 1;
101         qR = t[y].ti;
102         ret = max(ret, query(1, 2, n));
103     }
104     return ret;
105 }
106 
107 
108 void init()
109 {
110     memset(maxv, 0, sizeof(maxv));
111     dfs_clock = 0;
112     scanf("%d", &n);
113     for (int i = 0; i <= n; i++) G[i].clear();
114     e.clear();
115     int u, v, w;
116     for (int i = 1; i < n; i++)
117     {
118         scanf("%d%d%d", &u, &v, &w);
119         add_edge(u, v, w);
120     }
121 }
122 
123 void solve()
124 {
125     dfs1(1, 0, 1);
126     dfs2(1, 1);
127 
128     for (int i = 1; i < n; i++)
129     {
130         set_value = e[i-1].w;
131         if (t[e[i-1].u].dep < t[e[i-1].v].dep) 
132             qL = qR = t[e[i-1].v].ti;
133         else
134             qL = qR = t[e[i-1].u].ti;
135         update(1, 2, n);
136     }
137     char op[10];
138     int u, v;
139     while (true)
140     {
141         scanf("%s", op);
142         if (op[0] == D) break;
143         scanf("%d%d", &u, &v);
144         if (op[0] == Q) 
145         {
146             printf("%d\n", lca(u, v));
147         }
148         else
149         {
150             set_value = v;
151             if (t[e[u-1].u].dep < t[e[u-1].v].dep) 
152                 qL = qR = t[e[u-1].v].ti;
153             else
154                 qL = qR = t[e[u-1].u].ti;
155             update(1, 2, n);
156         }
157     }
158     printf("\n");
159 }
160 
161 int main()
162 {
163     int T;
164     scanf("%d", &T);
165     while (T--)
166     {
167         init();
168         solve();
169     }
170     return 0;
171 }

 

SPOJ QTREE Query on a tree

标签:i++   操作   code   ons   ++   深度   str   ack   双向   

原文地址:http://www.cnblogs.com/liangyongrui/p/6031347.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!