[POJ3237]Tree

仍然是树剖模板题TT

线段树维护取反和最大值就同时维护最大最小值,取反时最大最小值取反交换即可

单点修改时记得把叶节点的lazy tag置0

  1 #include<stdio.h>
  2 int h[10010],nex[20010],va[10010],vb[10010],ev[20010],to[20010],v[10010],siz[10010],son[10010],fa[10010],dep[10010],bl[10010],pos[10010],tot,sz,M,Tmin[40010],Tmax[40010],laz[40010];
  3 void add(int a,int b,int v){
  4     tot++;
  5     to[tot]=b;
  6     ev[tot]=v;
  7     nex[tot]=h[a];
  8     h[a]=tot;
  9 }
 10 void dfs(int x){
 11     siz[x]=1;
 12     int mx=0,k=0,i;
 13     for(i=h[x];i;i=nex[i]){
 14         if(to[i]!=fa[x]){
 15             fa[to[i]]=x;
 16             v[to[i]]=ev[i];
 17             dep[to[i]]=dep[x]+1;
 18             dfs(to[i]);
 19             siz[x]+=siz[to[i]];
 20             if(siz[to[i]]>mx){
 21                 mx=siz[to[i]];
 22                 k=to[i];
 23             }
 24         }
 25     }
 26     son[x]=k;
 27 }
 28 void dfs(int x,int chain){
 29     bl[x]=chain;
 30     sz++;
 31     pos[x]=sz;
 32     if(son[x])dfs(son[x],chain);
 33     for(int i=h[x];i;i=nex[i]){
 34         if(to[i]!=fa[x]&&to[i]!=son[x])dfs(to[i],to[i]);
 35     }
 36 }
 37 void pushdown(int x){
 38     if(laz[x]){
 39         int t=Tmin[x<<1];
 40         Tmin[x<<1]=-Tmax[x<<1];
 41         Tmax[x<<1]=-t;
 42         t=Tmin[x<<1|1];
 43         Tmin[x<<1|1]=-Tmax[x<<1|1];
 44         Tmax[x<<1|1]=-t;
 45         laz[x]=0;
 46         laz[x<<1]^=1;
 47         laz[x<<1|1]^=1;
 48     }
 49 }
 50 int min(int a,int b){return a<b?a:b;}
 51 int max(int a,int b){return a>b?a:b;}
 52 void pushup(int x){
 53     Tmin[x]=min(Tmin[x<<1],Tmin[x<<1|1]);
 54     Tmax[x]=max(Tmax[x<<1],Tmax[x<<1|1]);
 55 }
 56 void modify(int L,int R,int l,int r,int x){
 57     if(L<=l&&r<=R){
 58         laz[x]^=1;
 59         l=Tmin[x];
 60         Tmin[x]=-Tmax[x];
 61         Tmax[x]=-l;
 62         return;
 63     }
 64     pushdown(x);
 65     int mid=(l+r)>>1;
 66     if(L<=mid)modify(L,R,l,mid,x<<1);
 67     if(R>mid)modify(L,R,mid+1,r,x<<1|1);
 68     pushup(x);
 69 }
 70 void swap(int&a,int&b){a^=b^=a^=b;}
 71 void modify(int x,int y){
 72     while(bl[x]!=bl[y]){
 73         if(dep[bl[x]]<dep[bl[y]])swap(x,y);
 74         modify(pos[bl[x]],pos[x],1,M,1);
 75         x=fa[bl[x]];
 76     }
 77     if(x==y)return;
 78     if(pos[x]>pos[y])swap(x,y);
 79     modify(pos[x]+1,pos[y],1,M,1);
 80 }
 81 int querymax(int L,int R,int l,int r,int x){
 82     if(L<=l&&r<=R)return Tmax[x];
 83     pushdown(x);
 84     int mid=(l+r)>>1,ans=-2147483647;
 85     if(L<=mid)ans=max(ans,querymax(L,R,l,mid,x<<1));
 86     if(R>mid)ans=max(ans,querymax(L,R,mid+1,r,x<<1|1));
 87     return ans;
 88 }
 89 int getmax(int x,int y){
 90     int ans=-1061109567;
 91     while(bl[x]!=bl[y]){
 92         if(dep[bl[x]]<dep[bl[y]])swap(x,y);
 93         ans=max(ans,querymax(pos[bl[x]],pos[x],1,M,1));
 94         x=fa[bl[x]];
 95     }
 96     if(x==y)return ans;
 97     if(pos[x]>pos[y])swap(x,y);
 98     return max(ans,querymax(pos[x]+1,pos[y],1,M,1));
 99 }
100 void modifys(int pos,int v,int l,int r,int x){
101     if(l==r){
102         Tmax[x]=Tmin[x]=v;
103         laz[x]=0;
104         return;
105     }
106     pushdown(x);
107     int mid=(l+r)>>1;
108     if(pos<=mid)
109         modifys(pos,v,l,mid,x<<1);
110     else
111         modifys(pos,v,mid+1,r,x<<1|1);
112     pushup(x);
113 }
114 int main(){
115     int t,i,n,a,b;
116     char s[10];
117     scanf("%d",&t);
118     while(t--){
119         scanf("%d",&n);
120         tot=sz=0;
121         for(i=1;i<=n;i++)h[i]=0;
122         for(i=1;i<n;i++){
123             scanf("%d%d%d",va+i,vb+i,&a);
124             add(va[i],vb[i],a);
125             add(vb[i],va[i],a);
126         }
127         dfs(1);
128         dfs(1,1);
129         for(M=1;M<n+2;M<<=1);
130         for(i=0;i<(M<<1);i++){
131             Tmax[i]=-2147483647;
132             Tmin[i]=2147483647;
133             laz[i]=0;
134         }
135         for(i=1;i<=n;i++)Tmax[pos[i]+M-1]=Tmin[pos[i]+M-1]=v[i];
136         for(i=M-1;i>0;i--)pushup(i);
137         scanf("%s",s);
138         while(s[0]!=‘D‘){
139             scanf("%d%d",&a,&b);
140             if(s[0]==‘Q‘)printf("%d\n",getmax(a,b));
141             if(s[0]==‘N‘)modify(a,b);
142             if(s[0]==‘C‘){
143                 if(fa[va[a]]==vb[a])
144                     modifys(pos[va[a]],b,1,M,1);
145                 else
146                     modifys(pos[vb[a]],b,1,M,1);
147             }
148             scanf("%s",s);
149         }
150     }
151 }
时间: 2024-11-14 11:09:47

[POJ3237]Tree的相关文章

[POJ3237]Tree解题报告|树链剖分|边剖

关于边剖 之前做的大多是点剖,其实转换到边剖非常简单. 我的做法是每个点的点权记录其到父亲节点的边的边权. 只要solve的时候不要把最上面的点记录在内就可以了. 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

POJ3237 Tree(树链剖分 边权)

题目大意:指定一颗树上有3个操作:询问操作,询问a点和b点之间的路径上最长的那条边的长度:取反操作,将a点和b点之间的路径权值都取相反数:变化操作,把某条边的权值变成指定的值. #include <iostream> #include <algorithm> #include <cstring> #include <cmath> #include <queue> #include <map> #include <set>

【POJ3237】Tree(树链剖分)

题意:在一棵N个节点,有边权的树上维护以下操作: 1:单边修改,将第X条边的边权修改成Y 2:区间取反,将点X与Y在树上路径中的所有边边权取反 3:区间询问最大值,询问X到Y树上路径中边权最大值 n<=10000 CAS<=20 思路:做了2天,改出来的一刻全身都萎掉了 边权转点权,点权就是它到父亲的边的边权,加一些反向标记 取反的标记TAG下传时不能直接赋值为-1,而是将原先的标记取反 多组数据时倍增数组,深度也需要清零 树链剖分不能取第一条边,需要+1 1 const oo=2000000

【POJ3237】Tree 树链剖分+线段树

[POJ3237]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. Th

【POJ3237】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 throughN − 1. Each edge is associated with a weight. Then you are to execute a series of instructions on the tree. The instructions

【poj3237】 Tree

[http://poj.org/problem?id=3237] (题目链接) 树链剖分模板题,然而这150+行的程序我调了一天,历经艰辛,终于ac.. 题意:给出一个n个节点的带权树,要求维护操作:1.求出树上两点之间的边权的最大值:2.更改一条边上的权值:3.将树上两点之间的所有边权取各自的相反数. solution  神奇的树链剖分+线段树维护查询和修改操作.  树链剖分时,我们将每条边的权值转换为除树根外每个节点上的权值(也就是对于每个节点与它父亲的边的权值转换到了自己的权值).  之后

【poj3237】【Tree】

1583. [POJ3237]树的维护 ★★★☆ 输入文件: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:找出点a到点b路

【POJ3237】Tree 树链剖分

题意: change,把第i条边权值改成v negate,把a到b路径上所有权值取相反数(*(-1)) query,询问a到b路径上所有权值的最大值 树链剖分. 以前一直不会,但是我恶补LCT了,所以先学一下. 对于现在的水平来说,树剖太水了,自己翻资料吧,我只提供一个还算不错的代码. 扒代码的时候可以用我的这个. 附rand和pai. 代码: #include <cstdio> #include <cstring> #include <iostream> #inclu

poj3237

//Accepted 2280 KB 688 ms /* source:poj3237 time :2015.5.29 by :songt */ /*题解: 树链剖分 基于边权,路径查询最大值 线段树开到3倍RE,开到4倍AC */ #include <cstdio> #include <cstring> const int imax_n = 10005; const int inf = 0x3f3f3f3f; int max(int a,int b) { return a>