POJ 3237 Tree

题意是在一棵树上 的边上进行三个操作:

1.修改某条变得值

2.反转一条边的值

3.求出一条边上的max;

树上的操作+线段树

翻转的处理比较难 其他都是以前正常的线段树处理

翻转类似LAZY思想 ,然后我们设定MIN ,MAX,因为-MAX就是MIN 了,

线段树用回以前的版本了;

  1 #include <cstdio>
  2 #include <cstring>
  3 #include <string>
  4 #include <cmath>
  5 #include <iostream>
  6 #include <algorithm>
  7 #include <queue>
  8 #include <cstdlib>
  9 #include <stack>
 10 #include <vector>
 11 #include <set>
 12 #include <map>
 13 using namespace std;
 14 #define N 132222
 15 int head[N],top[N],fa[N],tot;
 16 int son[N],p[N],fp[N],dep[N],pos;
 17 int sz[N];
 18 void init()
 19 {
 20     memset(head,-1,sizeof(head));
 21     tot=0;
 22     pos=0;
 23     memset(son,-1,sizeof(son));
 24 }
 25 struct edge
 26 {
 27     int v,next;
 28 }e[N<<1];
 29 void add(int u,int v)
 30 {
 31    e[tot].v=v;
 32    e[tot].next=head[u];
 33    head[u]=tot++;
 34 }
 35 void dfs(int u,int f,int d)
 36 {
 37     dep[u]=d;
 38     fa[u]=f;
 39     sz[u]=1;
 40     for (int i=head[u];i!=-1;i=e[i].next)
 41     {
 42         int v=e[i].v;
 43         if (v==f) continue;
 44         dfs(v,u,d+1);
 45         sz[u]+=sz[v];
 46         if (son[u]==-1||sz[son[u]]<sz[v]) son[u]=v;
 47     }
 48 }
 49
 50 void getpos(int u,int sp)
 51 {
 52     top[u]=sp;
 53     p[u]=++pos;
 54     fp[pos]=u;
 55     if (son[u]==-1) return;
 56     getpos(son[u],sp);
 57     for (int i=head[u];i!=-1;i=e[i].next)
 58     {
 59         int v=e[i].v;
 60         if (v!=son[u]&&v!=fa[u])
 61             getpos(v,v);
 62     }
 63 }
 64
 65
 66 struct node
 67 {
 68     int l,r,Min,Max,flag;
 69 }tree[N<<2];
 70 void build(int l,int r,int rt)
 71 {
 72     tree[rt].l=l;
 73     tree[rt].r=r;
 74     tree[rt].Min=tree[rt].Max=0;
 75     tree[rt].flag=0;
 76     if (l==r) return;
 77     int m=(l+r)>>1;
 78     build(l,m,rt<<1);
 79     build(m+1,r,rt<<1|1);
 80 }
 81
 82 void pushup(int rt)
 83 {
 84     tree[rt].Max=max(tree[rt<<1].Max,tree[rt<<1|1].Max);
 85     tree[rt].Min=min(tree[rt<<1].Min,tree[rt<<1|1].Min);
 86 }
 87
 88 void pushdown(int rt)
 89 {
 90     if (tree[rt].l==tree[rt].r) return;
 91     if (tree[rt].flag)
 92     {
 93         tree[rt<<1].Max=-tree[rt<<1].Max;
 94         tree[rt<<1].Min=-tree[rt<<1].Min;
 95         swap(tree[rt<<1].Max,tree[rt<<1].Min);
 96
 97         tree[rt<<1|1].Max=-tree[rt<<1|1].Max;
 98         tree[rt<<1|1].Min=-tree[rt<<1|1].Min;
 99         swap(tree[rt<<1|1].Max,tree[rt<<1|1].Min);
100         tree[rt<<1].flag^=1;
101         tree[rt<<1|1].flag^=1;
102         tree[rt].flag=0;
103     }
104 }
105
106 void update(int p,int c,int rt)
107 {
108     if (tree[rt].l==p&&tree[rt].r==p)
109     {
110         tree[rt].Max=c;
111         tree[rt].Min=c;
112         tree[rt].flag=0;
113         return;
114     }
115     pushdown(rt);
116     int mid=(tree[rt].l+tree[rt].r)>>1;
117     if (p<=mid) update(p,c,rt<<1);
118     else update(p,c,rt<<1|1);
119     pushup(rt);
120 }
121
122 void neupdate(int l,int r,int rt)
123 {
124     if (tree[rt].l==l&&tree[rt].r==r)
125     {
126         tree[rt].Max=-tree[rt].Max;
127         tree[rt].Min=-tree[rt].Min;
128         swap(tree[rt].Max,tree[rt].Min);
129         tree[rt].flag^=1;
130         return;
131     }
132     pushdown(rt);
133     int mid=(tree[rt].l+tree[rt].r)>>1;
134     if (r<=mid) neupdate(l,r,rt<<1);
135     else if (l>mid) neupdate(l,r,rt<<1|1);
136     else
137     {
138         neupdate(l,mid,rt<<1);
139         neupdate(mid+1,r,rt<<1|1);
140     }
141     pushup(rt);
142 }
143
144 int query(int l,int r,int rt)
145 {
146     if (tree[rt].l==l&&tree[rt].r==r) return tree[rt].Max;
147     pushdown(rt);
148     int mid=(tree[rt].l+tree[rt].r)>>1;
149     if (r<=mid) return query(l,r,rt<<1);
150     else if (l>mid) return query(l,r,rt<<1|1);
151     else return max(query(l,mid,rt<<1),query(mid+1,r,rt<<1|1));
152     pushup(rt);
153 }
154
155 int lca(int u,int v)
156 {
157     int fu=top[u],fv=top[v];
158     int tmp=-1234567;
159     while (fu!=fv)
160     {
161         if (dep[fu]<dep[fv])
162         {
163             swap(fu,fv);
164             swap(u,v);
165         }
166         tmp=max(tmp,query(p[fu],p[u],1));
167         u=fa[fu];
168         fu=top[u];
169     }
170     if (u==v) return tmp;
171     if (dep[u]>dep[v]) swap(u,v);
172     return max(tmp,query(p[son[u]],p[v],1));
173 }
174
175 void Negat(int u,int v)
176 {
177     int fu=top[u],fv=top[v];
178     while (fu!=fv)
179     {
180         if (dep[fu]<dep[fv])
181         {
182             swap(fu,fv);
183             swap(u,v);
184         }
185         neupdate(p[fu],p[u],1);
186         u=fa[fu];
187         fu=top[u];
188     }
189     if (u==v) return;
190     if (dep[u]>dep[v]) swap(u,v);
191     neupdate(p[son[u]],p[v],1);
192 }
193
194 int a[N][3];
195 int main()
196 {
197     int T;
198     scanf("%d",&T);
199     while (T--)
200     {
201         int n;
202         init();
203         scanf("%d",&n);
204         for (int i=1;i<n;i++){
205             scanf("%d%d%d",&a[i][0],&a[i][1],&a[i][2]);
206             add(a[i][0],a[i][1]);
207             add(a[i][1],a[i][0]);
208         }
209
210         dfs(1,0,0);
211         getpos(1,1);
212         build(1,pos,1);
213         for (int i=1;i<n;i++)
214         {
215             if (dep[a[i][0]]>dep[a[i][1]]) swap(a[i][0],a[i][1]);
216             update(p[a[i][1]],a[i][2],1);
217         }
218          //printf("rerEt\n");
219
220         char s[10];
221         while (scanf("%s",s)!=EOF)
222         {
223             if (s[0]==‘D‘) break;
224             int u,v;
225             scanf("%d%d",&u,&v);
226             if (s[0]==‘Q‘)
227                printf("%d\n",lca(u,v));
228             else if (s[0]==‘N‘) Negat(u,v);
229             else  update(p[a[u][1]],v,1);
230         }
231     }
232     return 0;
233 }
时间: 2024-10-06 07:39:27

POJ 3237 Tree的相关文章

poj 3237 Tree(树链拆分)

题目链接:poj 3237 Tree 题目大意:给定一棵树,三种操作: CHANGE i v:将i节点权值变为v NEGATE a b:将ab路径上全部节点的权值变为相反数 QUERY a b:查询ab路径上节点权值的最大值. 解题思路:树链剖分.然后用线段树维护节点权值,成端更新查询. #include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int max

poj 3237 Tree(树链剖分,线段树)

Tree Time Limit: 5000MS   Memory Limit: 131072K Total Submissions: 7268   Accepted: 1969 Description You are given a tree with N nodes. The tree’s nodes are numbered 1 through N and its edges are numbered 1 through N − 1. Each edge is associated with

POJ 3237 Tree (树链剖分 路径剖分 线段树的lazy标记)

题目链接:http://poj.org/problem?id=3237 一棵有边权的树,有3种操作. 树链剖分+线段树lazy标记.lazy为0表示没更新区间或者区间更新了2的倍数次,1表示为更新,每次更新异或1就可以. 熟悉线段树成段更新就很简单了,最初姿势不对一直wa,还是没有彻底理解lazy标记啊. 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 using namespace st

poj 3237 Tree 树链剖分+线段树

Description You are given a tree with N nodes. The tree's nodes are numbered 1 through N and its edges are numbered 1 through N ? 1. Each edge is associated with a weight. Then you are to execute a series of instructions on the tree. The instructions

树链剖分 [POJ 3237] Tree

Tree Description You are given a tree with N nodes. The tree’s nodes are numbered 1 through N and its edges are numbered 1 through N − 1. Each edge is associated with a weight. Then you are to execute a series of instructions on the tree. The instruc

POJ 3237 Tree 树链剖分

单点替换,区间取相反数,区间求最大值,其实线段树里面只要保存最小值和最大值就可以了,取反之后最小值变成最大值最大值变成最小值. #include <cstdio> #include <cstring> #include <algorithm> #include <map> #include <set> #include <bitset> #include <queue> #include <stack> #in

(树链剖分+线段树)POJ - 3237 Tree

前言: 一直听说树链剖分-树链剖分,现在见识一下,,,感觉不是很难0.0 看了一下kuangbin模板基本秒懂 对于点,按重边优先给予每个点一个编号,对于一条重链上的点,编号则是连续的,将所有编号映射到线段树上,即可进行一切区间操作. 对于边的处理,我们将所有边对应到这条边节点更深的那个点上即可. 如果需要的操作只有求和,和单点更新/区间更新,直接用树状数组也是可以的,可能常数大那么一点点. 如果还需要更加强大的操作,显然用splay树维护也是可以的.. 比如树链上所有权值翻转等等..不过,,这

POJ 3723 Tree(树链剖分)

POJ 3237 Tree 题目链接 就多一个取负操作,所以线段树结点就把最大和最小值存下来,每次取负的时候,最大和最小值取负后,交换即可 代码: #include <cstdio> #include <cstring> #include <vector> #include <algorithm> using namespace std; const int N = 10005; const int INF = 0x3f3f3f3f; int dep[N],

cogs 1583. [POJ 3237] 树的维护 树链剖分套线段树

1583. [POJ 3237] 树的维护 ★★★★   输入文件:maintaintree.in   输出文件:maintaintree.out   简单对比时间限制:5 s   内存限制:128 MB [题目描述] 给你由N个结点组成的树.树的节点被编号为1到N,边被编号为1到N-1.每一条边有一个权值.然后你要在树上执行一系列指令.指令可以是如下三种之一: CHANGE i v:将第i条边的权值改成v. NEGATE a b:将点a到点b路径上所有边的权值变成其相反数. QUERY a b