写了5KB,1发AC。。。

题意:给出一颗树,支持5种操作。

1.修改某条边的权值。2.将u到v的经过的边的权值取负。3.求u到v的经过的边的权值总和。4.求u到v的经过的边的权值最大值。5.求u到v经过的边的权值最小值。

基于边权的树链剖分,放在线段树上变成了区间维护问题了,线段树维护4个量min,max,sum,tag就可以了。

# include <cstdio>
# include <cstring>
# include <cstdlib>
# include <iostream>
# include <vector>
# include <queue>
# include <stack>
# include <map>
# include <bitset>
# include <set>
# include <cmath>
# include <algorithm>
using namespace std;
# define lowbit(x) ((x)&(-x))
# define pi acos(-1.0)
# define eps 1e-
# define MOD
# define INF
# define mem(a,b) memset(a,b,sizeof(a))
# define FOR(i,a,n) for(int i=a; i<=n; ++i)
# define FO(i,a,n) for(int i=a; i<n; ++i)
# define bug puts("H");
# define lch p<<,l,mid
# define rch p<<|,mid+,r
# define mp make_pair
# define pb push_back
typedef pair<int,int> PII;
typedef vector<int> VI;
# pragma comment(linker, "/STACK:1024000000,1024000000")
typedef long long LL;
int Scan() {
int x=,f=;char ch=getchar();
while(ch<''||ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch>=''&&ch<=''){x=x*+ch-'';ch=getchar();}
return x*f;
}
const int N=;
//Code begin... struct Edge{int p, next;}edge[N<<];
struct Seg{int sum, ma, mi;}seg[N<<];
bool tag[N<<];
int head[N], cnt=, E[N][], n;
int top[N], fa[N], deep[N], num[N], p[N], fp[N], son[N], pos; void add_edge(int u, int v){
edge[cnt].p=v; edge[cnt].next=head[u]; head[u]=cnt++;
}
void init(){mem(son,-); pos=;}
void dfs1(int u, int pre, int d){
deep[u]=d; fa[u]=pre; num[u]=;
for (int i=head[u]; i; i=edge[i].next) {
int v=edge[i].p;
if (v==pre) continue;
dfs1(v,u,d+); num[u]+=num[v];
if (son[u]==-||num[v]>num[son[u]]) son[u]=v;
}
}
void getpos(int u, int sp){
top[u]=sp; p[u]=pos++; fp[p[u]]=u;
if (son[u]==-) return ;
getpos(son[u],sp);
for (int i=head[u]; i; i=edge[i].next) {
int v=edge[i].p;
if (v!=son[u]&&v!=fa[u]) getpos(v,v);
}
}
void push_up(int p){
seg[p].sum=seg[p<<].sum+seg[p<<|].sum;
seg[p].ma=max(seg[p<<].ma,seg[p<<|].ma);
seg[p].mi=min(seg[p<<].mi,seg[p<<|].mi);
}
void push_down(int p){
if (!tag[p]) return ;
seg[p].sum=-seg[p].sum; swap(seg[p].ma,seg[p].mi); seg[p].ma=-seg[p].ma; seg[p].mi=-seg[p].mi;
tag[p<<]^=tag[p]; tag[p<<|]^=tag[p]; tag[p]=false;
}
void Update(int p, int l, int r, int L, int val){
push_down(p);
if (L>r||L<l) return ;
if (L==l&&L==r) seg[p].ma=seg[p].mi=seg[p].sum=val;
else {
int mid=(l+r)>>;
Update(lch,L,val); Update(rch,L,val); push_up(p);
}
}
void Inv(int p, int l, int r, int L, int R){
push_down(p);
if (L>r||R<l) return ;
if (L<=l&&R>=r) tag[p]^=, push_down(p);
else {
int mid=(l+r)>>;
Inv(lch,L,R); Inv(rch,L,R); push_up(p);
}
}
int Query_Max(int p, int l, int r, int L, int R){
push_down(p);
if (L>r||R<l) return -INF;
if (L<=l&&R>=r) return seg[p].ma;
int mid=(l+r)>>;
return max(Query_Max(lch,L,R),Query_Max(rch,L,R));
}
int Query_Min(int p, int l, int r, int L, int R){
push_down(p);
if (L>r||R<l) return INF;
if (L<=l&&R>=r) return seg[p].mi;
int mid=(l+r)>>;
return min(Query_Min(lch,L,R),Query_Min(rch,L,R));
}
int Query_Sum(int p, int l, int r, int L, int R){
push_down(p);
if (L>r||R<l) return ;
if (L<=l&&R>=r) return seg[p].sum;
int mid=(l+r)>>;
return Query_Sum(lch,L,R)+Query_Sum(rch,L,R);
}
int Sol(int u, int v, int flag){
int f1=top[u], f2=top[v], ans;
if (flag==) ans=;
else if (flag==) ans=-INF;
else ans=INF;
while (f1!=f2) {
if (deep[f1]<deep[f2]) swap(f1,f2), swap(u,v);
if (flag==) Inv(,,n,p[f1],p[u]);
else if (flag==) ans+=Query_Sum(,,n,p[f1],p[u]);
else if (flag==) ans=max(ans,Query_Max(,,n,p[f1],p[u]));
else ans=min(ans,Query_Min(,,n,p[f1],p[u]));
u=fa[f1]; f1=top[u];
}
if (u==v) return ans;
if (deep[u]>deep[v]) swap(u,v);
if (flag==) {Inv(,,n,p[son[u]],p[v]); return ;}
else if (flag==) return ans+Query_Sum(,,n,p[son[u]],p[v]);
else if (flag==) return max(ans,Query_Max(,,n,p[son[u]],p[v]));
else return min(ans,Query_Min(,,n,p[son[u]],p[v]));
}
int main ()
{
int m, x, y;
char s[];
scanf("%d",&n); init();
FO(i,,n) scanf("%d%d%d",&E[i][],&E[i][],&E[i][]), ++E[i][], ++E[i][], add_edge(E[i][],E[i][]), add_edge(E[i][],E[i][]);
dfs1(,,); getpos(,);
FO(i,,n) {
if (deep[E[i][]]>deep[E[i][]]) swap(E[i][],E[i][]);
Update(,,n,p[E[i][]],E[i][]);
}
scanf("%d",&m);
while (m--) {
scanf("%s%d%d",s,&x,&y);
if (!strcmp(s,"C")) Update(,,n,p[E[x][]],y);
else if (!strcmp(s,"N")) ++x, ++y, Sol(x,y,);
else if (!strcmp(s,"SUM")) ++x, ++y, printf("%d\n",Sol(x,y,));
else if (!strcmp(s,"MAX")) ++x, ++y, printf("%d\n",Sol(x,y,));
else ++x, ++y, printf("%d\n",Sol(x,y,));
}
return ;
}

BZOJ 2157 旅行(树链剖分码农题)的更多相关文章

  1. BZOJ 2157: 旅游( 树链剖分 )

    树链剖分.. 样例太大了根本没法调...顺便把数据生成器放上来 -------------------------------------------------------------------- ...

  2. BZOJ 2157: 旅游 (树链剖分+线段树)

    树链剖分后线段树维护区间最大最小值与和. 支持单点修改与区间取反. 直接写个区间取反标记就行了.线段树板题.(200行6000B+ 1A警告) #include <cstdio> #inc ...

  3. BZOJ.3531.旅行(树链剖分 动态开点)

    题目链接 无优化版本(170行): /* 首先树剖可以维护树上的链Sum.Max 可以对每个宗教建一棵线段树,那这题就很好做了 不过10^5需要动态开点 (不明白为什么nlogn不需要回收就可以 不是 ...

  4. BZOJ 2243 染色 | 树链剖分模板题进阶版

    BZOJ 2243 染色 | 树链剖分模板题进阶版 这道题呢~就是个带区间修改的树链剖分~ 如何区间修改?跟树链剖分的区间询问一个道理,再加上线段树的区间修改就好了. 这道题要注意的是,无论是线段树上 ...

  5. BZOJ 3083 遥远的国度 树链剖分+线段树

    有换根的树链剖分的裸题. 在换根的时候注意讨论. 注意数据范围要开unsigned int或longlong #include<iostream> #include<cstdio&g ...

  6. BZOJ 3531 [Sdoi2014]旅行 树链剖分+动态开点线段树

    题意 S国有N个城市,编号从1到N.城市间用N-1条双向道路连接,满足从一个城市出发可以到达其它所有城市.每个城市信仰不同的宗教,如飞天面条神教.隐形独角兽教.绝地教都是常见的信仰. 为了方便,我们用 ...

  7. BZOJ 3531: [Sdoi2014]旅行 [树链剖分]

    3531: [Sdoi2014]旅行 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 1685  Solved: 751[Submit][Status] ...

  8. BZOJ 3531 SDOI2014 旅行 树链剖分+线段树动态开点

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=3531 题意概述: 给出一棵N个点的树,树上的每个结点有一个颜色和权值,支持以下四种操作: ...

  9. BZOJ3531:[SDOI2014]旅行(树链剖分)

    Description S国有N个城市,编号从1到N.城市间用N-1条双向道路连接,满足 从一个城市出发可以到达其它所有城市.每个城市信仰不同的宗教,如飞天面条神教.隐形独角兽教.绝地教都是常见的信仰 ...

随机推荐

  1. 2017-2018-2 《网络对抗技术》 20155322 第二周 Exp1 PC平台逆向破解(5)M

    #2017-2018-2 <网络对抗技术> 20155322 第二周 Exp1 PC平台逆向破解(5)M [博客目录] 1-实践目标 1.1-实践介绍 1.2-实践内容 1.3-实践要求 ...

  2. vim 中文乱码问题

    编辑~/.vimrc文件,加上如下几行: set fileencodings=utf-8,ucs-bom,gb18030,gbk,gb2312,cp936   set termencoding=utf ...

  3. 深入Redis 主从复制原理

    原文:深入Redis 主从复制原理 1.复制过程 2.数据间的同步 3.全量复制 4.部分复制 5.心跳 6.异步复制 1.复制过程 从节点执行 slaveof 命令. 从节点只是保存了 slaveo ...

  4. oracle基础命令

    oracle使用步骤: 一.oracle安装 两个文件解压到同一文件夹,doc为说明/使用文档 二.oracle启动: 1.启动oracle:启动监听和自定义库 2.启动cmd->sqlplus ...

  5. 【转载】GitHub详解

    原文:GitHub详解 GitHub详解 GitHub 是一个共享虚拟主机服务,用于存放使用Git版本控制的软件代码和内容项目.它由GitHub公司(曾称Logical Awesome)的开发者Chr ...

  6. 1. oracle12C的安装

    官方安装文档:https://docs.oracle.com/database/121/LTDQI/toc.htm#BHCCADGD 1.软件准备 oracle12c.zip 安装包 VMware 虚 ...

  7. 【mysql经典题目】行转列

    参考:http://www.cnblogs.com/h07061108/p/mysql_questions.html#3806338 实现如下效果 CREATE TABLE IF NOT EXISTS ...

  8. selenium webdriver API详解(二)

    本系列主要讲解webdriver常用的API使用方法(注意:使用前请确认环境是否安装成功,浏览器驱动是否与谷歌浏览器版本对应) 一:获取当前页面的title(一般获取title用于断言) from s ...

  9. php文章tag标签的增删

    <?php session_start();   if($_POST){           $_SESSION['old']=array('one','two','three','four', ...

  10. JAVA学习笔记--接口

    一.抽象类和抽象方法 在谈论接口之前,我们先了解一下抽象类和抽象方法.我们知道,在继承结构中,越往下继承,类会变得越来越明确和具体,而往上回溯,越往上,类会变得越抽象和通用.我们有时候可能会需要这样一 ...