题意:给一棵树,三种操作。将第i条边的权值改为v,将a到b的路径上的边的权值全部取反,求a到b路径上边的权值的最大值。

思路:明显的树链剖分,加上线段树的操作。因为有取反的操作所以每个区间要记录最大值和最小值。查询两点间的路径时,用求公共祖先的方式去求。

#include<iostream>
#include<stdio.h>
#include<string.h>
const int N=101000;
const int inf=0x3fffffff;
using namespace std;
int head[N],num,son[N],sz[N],father[N],dep[N],idx,a[N],cot[N],ti[N],top[N];
struct edge
{
int st,ed,w,next;
}e[N*4];
void addedge(int x,int y,int w)
{
e[num].st=x;e[num].ed=y;e[num].w=w;e[num].next=head[x];head[x]=num++;
e[num].st=y;e[num].ed=x;e[num].w=w;e[num].next=head[y];head[y]=num++;
}
int max(int a,int b)
{
if(a>b)return a;
return b;
}
int min(int a,int b)
{
if(a>b)return b;
return a;
}
//******************树链剖分****************************
void find_son(int u,int fa)
{
int i,v;
son[u]=0;sz[u]=1;
for(i=head[u];i!=-1;i=e[i].next)
{
v=e[i].ed;
if(v==fa)continue;
father[v]=u;
dep[v]=dep[u]+1;
a[v]=e[i].w;
find_son(v,u);
sz[u]+=sz[v];
if(sz[v]>sz[son[u]])son[u]=v;
}
}
void find_time(int u,int fa)
{
int i,v;
ti[u]=idx++;
cot[ti[u]]=a[u];
top[u]=fa;
if(son[u]!=0)find_time(son[u],top[u]);
for(i=head[u];i!=-1;i=e[i].next)
{
v=e[i].ed;
if(v==son[u]||v==father[u])continue;
find_time(v,v);
}
}
//***********************线段树*********************
struct Tree
{
int L,R,Mw,mw;
int flag;//该区间是否取反
}T[N*10];
void up(int id)
{
int li=id<<1,ri=li|1;
T[id].Mw=max(T[li].Mw,T[ri].Mw);
T[id].mw=min(T[li].mw,T[ri].mw);
}
void buildTree(int L,int R,int id)
{
T[id].L=L;T[id].R=R;T[id].flag=0;
if(L==R)
{
T[id].Mw=T[id].mw=cot[L];
return;
}
int mid=(L+R)>>1,li=id<<1,ri=li|1;
buildTree(L,mid,li);
buildTree(mid+1,R,ri);
up(id);
}
void fan(int id)
{
if(T[id].L==T[id].R)return ;
int li=id<<1,ri=li|1;
T[id].flag=0;//传递给两个子区间后该区间上不取反
T[li].flag^=1;T[ri].flag^=1;
T[li].Mw*=-1;T[li].mw*=-1;
T[ri].Mw*=-1;T[ri].mw*=-1;
swap(T[li].Mw,T[li].mw);
swap(T[ri].Mw,T[ri].mw);
}
void Negate(int L,int R,int id)//取反操作
{
if(T[id].L==L&&T[id].R==R)
{
T[id].Mw*=-1;
T[id].mw*=-1;
swap(T[id].Mw,T[id].mw);
T[id].flag^=1;
return ;
}
int mid=(T[id].L+T[id].R)>>1,li=id<<1,ri=li|1;
if(T[id].flag)
{
fan(id);
}
if(R<=mid)Negate(L,R,li);
else if(L>mid)Negate(L,R,ri);
else
{
Negate(L,mid,li);
Negate(mid+1,R,ri);
}
up(id);
}
void insert(int x,int id,int w)//更新x的值
{
if(T[id].L==x&&T[id].R==x)
{
T[id].Mw=T[id].mw=w;
T[id].flag=0;
return ;
}
int mid=(T[id].L+T[id].R)>>1,li=id<<1,ri=li|1;
if(T[id].flag)
fan(id);
if(x<=mid)insert(x,li,w);
else insert(x,ri,w);
up(id);
}
int find(int L,int R,int id)//找最大值
{
if(T[id].L==L&&T[id].R==R)
{
return T[id].Mw;
}
int mid=(T[id].L+T[id].R)>>1,li=id<<1,ri=li|1;
if(T[id].flag)
fan(id);
if(R<=mid)return find(L,R,li);
else if(L>mid)return find(L,R,ri);
else return max(find(L,mid,li),find(mid+1,R,ri));
up(id);
}
int lca(int x,int y)//x到y路径上的最大值
{
int ans=-inf;
while(top[x]!=top[y])
{
if(dep[top[x]]<dep[top[y]])swap(x,y);
ans=max(ans,find(ti[top[x]],ti[x],1));
x=father[top[x]];
}
if(dep[x]>dep[y])swap(x,y);
if(x!=y)
ans=max(ans,find(ti[x]+1,ti[y],1));
return ans;
}
void LCA(int x,int y)//x到y路径权值取反
{
while(top[x]!=top[y])
{
if(dep[top[x]]<dep[top[y]])swap(x,y);
Negate(ti[top[x]],ti[x],1);
x=father[top[x]];
}
if(dep[x]>dep[y])swap(x,y);
if(x!=y)
Negate(ti[x]+1,ti[y],1);//ti[x]是x与父节点的边
}
int main()
{
int i,n,t,x,y,w;
char str[10];
scanf("%d",&t);
while(t--)
{
memset(head,-1,sizeof(head));
num=0;
scanf("%d",&n);
for(i=1;i<n;i++)
{
scanf("%d%d%d",&x,&y,&w);
addedge(x,y,w);
}
dep[1]=1;
sz[0]=father[1]=0;idx=1;
find_son(1,0);
find_time(1,1);
buildTree(1,n,1);
while(scanf("%s",str),str[0]!='D')
{
scanf("%d%d",&x,&y);
if(str[0]=='C')
{
x=x*2-2;
if(dep[e[x].st]>dep[e[x].ed])//每条边的取值在度数大的点上
swap(e[x].st,e[x].ed);
insert(ti[e[x].ed],1,y);
}
else if(str[0]=='N')
LCA(x,y);
else
printf("%d\n",lca(x,y));
}
}
return 0;
}

poj 3237(树链剖分+线段树)的更多相关文章

  1. POJ.2763 Housewife Wind ( 边权树链剖分 线段树维护区间和 )

    POJ.2763 Housewife Wind ( 边权树链剖分 线段树维护区间和 ) 题意分析 给出n个点,m个询问,和当前位置pos. 先给出n-1条边,u->v以及边权w. 然后有m个询问 ...

  2. 【BZOJ-2325】道馆之战 树链剖分 + 线段树

    2325: [ZJOI2011]道馆之战 Time Limit: 40 Sec  Memory Limit: 256 MBSubmit: 1153  Solved: 421[Submit][Statu ...

  3. 【BZOJ2243】[SDOI2011]染色 树链剖分+线段树

    [BZOJ2243][SDOI2011]染色 Description 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询问节点a到节点b路径上的 ...

  4. BZOJ2243 (树链剖分+线段树)

    Problem 染色(BZOJ2243) 题目大意 给定一颗树,每个节点上有一种颜色. 要求支持两种操作: 操作1:将a->b上所有点染成一种颜色. 操作2:询问a->b上的颜色段数量. ...

  5. POJ3237 (树链剖分+线段树)

    Problem Tree (POJ3237) 题目大意 给定一颗树,有边权. 要求支持三种操作: 操作一:更改某条边的权值. 操作二:将某条路径上的边权取反. 操作三:询问某条路径上的最大权值. 解题 ...

  6. bzoj4034 (树链剖分+线段树)

    Problem T2 (bzoj4034 HAOI2015) 题目大意 给定一颗树,1为根节点,要求支持三种操作. 操作 1 :把某个节点 x 的点权增加 a . 操作 2 :把某个节点 x 为根的子 ...

  7. HDU4897 (树链剖分+线段树)

    Problem Little Devil I (HDU4897) 题目大意 给定一棵树,每条边的颜色为黑或白,起始时均为白. 支持3种操作: 操作1:将a->b的路径中的所有边的颜色翻转. 操作 ...

  8. Aizu 2450 Do use segment tree 树链剖分+线段树

    Do use segment tree Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://www.bnuoj.com/v3/problem_show ...

  9. 【POJ3237】Tree(树链剖分+线段树)

    Description You are given a tree with N nodes. The tree’s nodes are numbered 1 through N and its edg ...

  10. HDU 2460 Network(双连通+树链剖分+线段树)

    HDU 2460 Network 题目链接 题意:给定一个无向图,问每次增加一条边,问个图中还剩多少桥 思路:先双连通缩点,然后形成一棵树,每次增加一条边,相当于询问这两点路径上有多少条边,这个用树链 ...

随机推荐

  1. FastReport.Net使用:[15]富文本控件使用

    富文本(Rich Text)控件用于显示Rtf格式的文本. 认识富文本编辑窗体 1.下图就是富文本的编辑窗体,乍一看就像Word一样,不过功能没有Word强大了.具体功能就不一一介绍了,用个Word的 ...

  2. java8新特性——时间日期API

    传统的时间 API 存在线程安全的问题,在多线程开发中必须要上锁,所以 java8 现在为我们提供了一套全新的时间日期 API ,今天进来学习一下java8 的时间日期 API. 一.使用 Local ...

  3. BZOJ1021 SHOI2008循环的债务

    dp模拟即可. d[i][j][k]表示使用前i种面值,1号手里钱为j,2号手里钱为k时最少操作数 使用滚动数组压缩空间 #include <cstdio> #include <cs ...

  4. Linux的十个最危险的命令

    Linux命令行佷有用.很高效,也很有趣,但有时候也很危险,尤其是在你不确定你自己在正在做什么时候. 这篇文章将会向你介绍十条命令,但你最好不要尝试着去使用. 当然,以下命令通常都是在root权限下才 ...

  5. [AtCoder-ARC073F]Many Moves

    题目大意: 有一排n个格子和2枚硬币. 现在有q次任务,每一次要你把其中一枚硬币移到x的位置上,移动1格的代价是1. 两枚硬币不能同时移动,任务必须按次序完成. 现在告诉你两枚硬币初始状态所在的位置a ...

  6. [转]ADT中通过DDMS导入文件出错ddms transfer error: Read-only file system,Failed to push selection: Read-only file system

    [已解决] 原文  http://www.crifan.com/ddms_import_file_error_transfer_error_read_only_file_system/ 想要通过adt ...

  7. VK Cup 2016 - Qualification Round 1 (Russian-Speaking Only, for VK Cup teams) C. Promocodes with Mistakes 水题

    C. Promocodes with Mistakes 题目连接: http://www.codeforces.com/contest/637/problem/C Description During ...

  8. 使用 dsc_extractor 导出 dyld_shared_cache_arm64

    iOS系统的全部Framework二进制被打包成一个cache文件,位于 /System/Library/Caches/com.apple.dyld 目录下,我们要想查看某个系统库的二进制需要将 dy ...

  9. LT3759 宽输入电压范围升压 / 负输出 / SEPIC 控制器 可在输入电压低至 1.6V 的情况下工作

    引言当今的许多电子设备都需要一个负输出或正输出转换器,有时则是两者均需要.另外,它们还必需采用各种电源运作,包括 USB.墙上适配器.碱性电池和锂电池等. 为了从可变输入电压产生不同极性的输出,电源设 ...

  10. matlab mex中C++内存全局共享和持久化

    为提高matlab程序运行速度,经常将核心程序编写为mex动态链接库: 然而,经常情况下,在mex函数中分配的内存或句柄希望在mex函数调用完成后在后续函数调用中能够共享而不被释放,本程序方法为解决该 ...