POJ3237 Tree(树剖+线段树+lazy标记)
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 can be one of the following forms:
CHANGE i v |
Change the weight of the ith edge to v |
NEGATE a b |
Negate the weight of every edge on the path from a to b |
QUERY a b |
Find the maximum weight of edges on the path from a to b |
Input
The input contains multiple test cases. The first line of input contains an integer t (t ≤ 20), the number of test cases. Then follow the test cases.
Each test case is preceded by an empty line. The first nonempty line of its contains N (N ≤ 10,000). The next N − 1 lines each contains three integers a, b and c, describing an edge connecting nodes a and b with weight c. The edges are numbered in the order they appear in the input. Below them are the instructions, each sticking to the specification above. A lines with the word “DONE” ends the test case.
Output
For each “QUERY” instruction, output the result on a separate line.
Sample Input
1 3
1 2 1
2 3 2
QUERY 1 2
CHANGE 1 3
QUERY 1 2
DONE
Sample Output
1
3
题意:
对于一棵树,有几种操作:
Q :x y 。问x到y之间的路径的最大边权值为多少。
C :x y。把第x条边的权值改为y。
N:x y。把x到y之间的边权值取反。
D。结束。
思路:
和前面一道树剖题的查询是一样的,所以同样需要树剖+线段树,对于C操作,同样是线段树单点更新即可。但是需要区间权值取反,得用lazy标记一下。记录最大和最小值,方便在取反后还能得到最大值。
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
#define min(a,b) (a<b?a:b)
#define max(a,b) (a>b?a:b)
#define swap(a,b) (a^=b,b^=a,a^=b)
using namespace std;
const int maxn=;
int Laxt[maxn],Next[maxn],To[maxn],e[maxn][],cnt;
int n,q; char opt[];
struct TreeCut
{
int dpt[maxn],top[maxn],son[maxn],fa[maxn],sz[maxn],tot;
int tid[maxn],Rank[maxn],tim;
int Max[maxn<<],Min[maxn<<],Lazy[maxn<<];
void init()
{
cnt=; tim=;
memset(Laxt,,sizeof(Laxt));
memset(Max,,sizeof(Max));
memset(Min,,sizeof(Min));
memset(Lazy,,sizeof(Lazy));
}
void add_edge(int u,int v)
{
Next[++cnt]=Laxt[u];
Laxt[u]=cnt; To[cnt]=v;
}
void dfs1(int u,int pre)
{
fa[u]=pre;dpt[u]=dpt[pre]+;sz[u]=;son[u]=;
for(int i=Laxt[u];i;i=Next[i]){
int v=To[i]; if(v==pre) continue;
dfs1(v,u);sz[u]+=sz[v];
if(!son[u]||sz[v]>sz[son[u]]) son[u]=v;
}
}
void pushdown(int Now)
{
swap(Max[Now<<],Min[Now<<]),Max[Now<<]=-Max[Now<<],Min[Now<<]=-Min[Now<<];
swap(Max[Now<<|],Min[Now<<|]),Max[Now<<|]=-Max[Now<<|],Min[Now<<|]=-Min[Now<<|];
Lazy[Now<<]^=;Lazy[Now<<|]^=;Lazy[Now]=;
}
void pushup(int Now)
{
Max[Now]=max(Max[Now<<],Max[Now<<|]);
Min[Now]=min(Min[Now<<],Min[Now<<|]);
}
void dfs2(int u,int Top)
{
top[u]=Top; tid[u]=tim++;Rank[tid[u]]=u;
if(!son[u]) return ; dfs2(son[u],Top);
for(int i=Laxt[u];i;i=Next[i])
if(To[i]!=fa[u]&&To[i]!=son[u]) dfs2(To[i],To[i]);
}
void update(int Now,int L,int R,int pos,int val)
{
if(L==R){ Max[Now]=Min[Now]=val; return; }
if(Lazy[Now]&) pushdown(Now);
int Mid=(L+R)>>;
if(Mid>=pos) update(Now<<,L,Mid,pos,val);
else update(Now<<|,Mid+,R,pos,val);
pushup(Now);
}
int getmax(int Now,int L,int R,int l,int r)
{
if(L>=l&&R<=r) return Max[Now];
if(Lazy[Now]&) pushdown(Now);
int Mid=(L+R)>>,ans=-0x7fffffff;
if(r<=Mid) ans=getmax(Now<<,L,Mid,l,r);
else if(l>Mid) ans=getmax(Now<<|,Mid+,R,l,r);
else ans=max(getmax(Now<<,L,Mid,l,Mid),getmax(Now<<|,Mid+,R,Mid+,r));
pushup(Now); return ans;
}
void addsign(int Now,int L,int R,int l,int r)
{
if(L>=l&&R<=r) {
Lazy[Now]^=;swap(Max[Now],Min[Now]);
Max[Now]=-Max[Now];Min[Now]=-Min[Now];
return ;
}
if(Lazy[Now]&) pushdown(Now);
int Mid=(L+R)>>;
if(l<=Mid) addsign(Now<<,L,Mid,l,r);
if(r>Mid) addsign(Now<<|,Mid+,R,l,r);
pushup(Now);
}
void Make_Tree()
{
scanf("%d",&n);
for(int i=;i<n;i++){
scanf("%d%d%d",&e[i][],&e[i][],&e[i][]);
add_edge(e[i][],e[i][]);add_edge(e[i][],e[i][]);
} dfs1(,); dfs2(,);
for(int i=;i<n;i++){
if(dpt[e[i][]]<dpt[e[i][]]) swap(e[i][],e[i][]);
update(,,n-,tid[e[i][]],e[i][]);
}
}
int query(int u,int v)
{
int f1=top[u],f2=top[v],ans=-0x7fffffff;
while(f1!=f2){
if(dpt[f1]<dpt[f2]) swap(f1,f2),swap(u,v);
ans=max(ans,getmax(,,n-,tid[f1],tid[u]));
u=fa[f1]; f1=top[u];
}
if(u!=v){
if(dpt[u]>dpt[v]) swap(u,v);
ans=max(ans,getmax(,,n-,tid[son[u]],tid[v]));
} printf("%d\n",ans);
}
int Add_lazy(int u,int v)
{
int f1=top[u],f2=top[v];
while(f1!=f2){
if(dpt[f1]<dpt[f2]) swap(f1,f2),swap(u,v);
addsign(,,n-,tid[f1],tid[u]);
u=fa[f1]; f1=top[u];
}
if(u!=v){
if(dpt[u]>dpt[v]) swap(u,v);
addsign(,,n-,tid[son[u]],tid[v]);
}
}
void Query()
{
while(~scanf("%s",opt)) {
if(opt[]=='D') return;
int x,y; scanf("%d%d",&x,&y);
if(opt[]=='Q') query(x,y);
else if(opt[]=='N') Add_lazy(x,y);
else update(,,n-,tid[e[x][]],y);
}
}
}Tc;
int main()
{
int T; scanf("%d",&T);
while(T--) {
Tc.init();
Tc.Make_Tree();
Tc.Query();
} return ;
}
POJ3237 Tree(树剖+线段树+lazy标记)的更多相关文章
- BZOJ_4551_[Tjoi2016&Heoi2016]树_树剖+线段树
BZOJ_4551_[Tjoi2016&Heoi2016]树_树剖+线段树 Description 在2016年,佳媛姐姐刚刚学习了树,非常开心.现在他想解决这样一个问题:给定一颗有根树(根为 ...
- BZOJ_2157_旅游_树剖+线段树
BZOJ_2157_旅游_树剖+线段树 Description Ray 乐忠于旅游,这次他来到了T 城.T 城是一个水上城市,一共有 N 个景点,有些景点之间会用一座桥连接.为了方便游客到达每个景点但 ...
- [LNOI2014]LCA(树剖+线段树)
\(\%\%\% Fading\) 此题是他第一道黑题(我的第一道黑题是蒲公英) 一直不敢开,后来发现是差分一下,将询问离线,树剖+线段树维护即可 \(Code\ Below:\) #include ...
- [CF1007D]Ants[2-SAT+树剖+线段树优化建图]
题意 我们用路径 \((u, v)\) 表示一棵树上从结点 \(u\) 到结点 \(v\) 的最短路径. 给定一棵由 \(n\) 个结点构成的树.你需要用 \(m\) 种不同的颜色为这棵树的树边染色, ...
- 洛谷P4315 月下“毛景树”(树剖+线段树)
传送门 woc这该死的码农题…… 把每一条边转化为它连接的两点中深度较深的那一个,然后就可以用树剖+线段树对路径进行修改了 然后顺便注意在上面这种转化之后,树剖的时候不能搞$LCA$ 然后是几个注意点 ...
- BZOJ_2238_Mst_树剖+线段树
BZOJ_2238_Mst_树剖+线段树 Description 给出一个N个点M条边的无向带权图,以及Q个询问,每次询问在图中删掉一条边后图的最小生成树.(各询问间独立,每次询问不对之后的询问产生影 ...
- 【BZOJ5210】最大连通子块和 树剖线段树+动态DP
[BZOJ5210]最大连通子块和 Description 给出一棵n个点.以1为根的有根树,点有点权.要求支持如下两种操作: M x y:将点x的点权改为y: Q x:求以x为根的子树的最大连通子块 ...
- LOJ#3088. 「GXOI / GZOI2019」旧词(树剖+线段树)
题面 传送门 题解 先考虑\(k=1\)的情况,我们可以离线处理,从小到大对于每一个\(i\),令\(1\)到\(i\)的路径上每个节点权值增加\(1\),然后对于所有\(x=i\)的询问查一下\(y ...
- BZOJ3531-[Sdoi2014]旅行(树剖+线段树动态开点)
传送门 完了今天才知道原来线段树的动态开点和主席树是不一样的啊 我们先考虑没有宗教信仰的限制,那么就是一个很明显的树剖+线段树,路径查询最大值以及路径和 然后有了宗教信仰的限制该怎么做呢? 先考虑暴力 ...
随机推荐
- VM tools安装错误The path "" is not a valid path to the xx generic kernel headers.
在网上搜索非常多解决方式.并不适用于我的问题,最后通过下面步骤解决: 1. 更新软件源(防止build-essential不能 安装),然后安装build-essential和linu-headers ...
- hibernate批量更新和删除数据
批量处理 不建议用Hibernate,它的insert效率实在不搞,不过最新版本的Hibernate似乎已经在批量处理的时候做过优化了,设置一些参数如batch_size,不过性能我没有测试过,听说 ...
- Python中strip方法的妙用
[开胃小菜] 当提到python中strip方法,想必凡接触过python的同行都知道它主要用来切除空格.有下面两种方法来实现. 方法一:用内置函数 #<python> if __name ...
- 对于一个字符串,请设计一个高效算法,找到第一次重复出现的字符。 给定一个字符串(不一定全为字母)A及它的长度n。请返回第一个重复出现的字符。保证字符串中有重复字符,字符串的长度小于等于500。
// 第一种方法 // ConsoleApplication10.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" #include < ...
- maven项目The superclass "javax.servlet.http.HttpServlet" was not found on the Java Build Path
用Eclipse创建了一个maven web程序,使用tomcat8.5作为服务器,可以正常启动,但是却报如下错误 The superclass "javax.servlet.http.Ht ...
- android 关于ScrollView 的博客做记录学习
1.Android ScrollView向上滑动控件顶部悬浮效果实现 2.[android]仿知乎ScrollView滚动改变标题栏透明度 3.github开源Android组件资源整理(五)Scro ...
- mfc 小程序---在系统菜单中添加菜单项
1建立一个对话框工程:在dlg类里定义一个菜单指针m_pMenu,在对话框OnInitDialog函数里添加代码: m_pMenu=GetSystemMenu(FALSE);//获取系统菜单的指针 m ...
- React常用方法手记
1.Reactjs 如何获取子组件的key值?请问antd中table自定义列render方法怎么获取当前第几列? https://segmentfault.com/q/101000000453235 ...
- ES6之路
从工作到现在,虽然是PHP出身,一直都和JS形影不离,从JQ和原生处理页面,到后来被angular1的MVVM模式惊艳到,再到弃angular转战vue,到现在使用react,一路走来,跳坑无数,现在 ...
- 【BZOJ4520】[Cqoi2016]K远点对 kd-tree+堆
[BZOJ4520][Cqoi2016]K远点对 Description 已知平面内 N 个点的坐标,求欧氏距离下的第 K 远点对. Input 输入文件第一行为用空格隔开的两个整数 N, K.接下来 ...