BZOJ 2157 旅行(树链剖分码农题)
写了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 旅行(树链剖分码农题)的更多相关文章
- BZOJ 2157: 旅游( 树链剖分 )
树链剖分.. 样例太大了根本没法调...顺便把数据生成器放上来 -------------------------------------------------------------------- ...
- BZOJ 2157: 旅游 (树链剖分+线段树)
树链剖分后线段树维护区间最大最小值与和. 支持单点修改与区间取反. 直接写个区间取反标记就行了.线段树板题.(200行6000B+ 1A警告) #include <cstdio> #inc ...
- BZOJ.3531.旅行(树链剖分 动态开点)
题目链接 无优化版本(170行): /* 首先树剖可以维护树上的链Sum.Max 可以对每个宗教建一棵线段树,那这题就很好做了 不过10^5需要动态开点 (不明白为什么nlogn不需要回收就可以 不是 ...
- BZOJ 2243 染色 | 树链剖分模板题进阶版
BZOJ 2243 染色 | 树链剖分模板题进阶版 这道题呢~就是个带区间修改的树链剖分~ 如何区间修改?跟树链剖分的区间询问一个道理,再加上线段树的区间修改就好了. 这道题要注意的是,无论是线段树上 ...
- BZOJ 3083 遥远的国度 树链剖分+线段树
有换根的树链剖分的裸题. 在换根的时候注意讨论. 注意数据范围要开unsigned int或longlong #include<iostream> #include<cstdio&g ...
- BZOJ 3531 [Sdoi2014]旅行 树链剖分+动态开点线段树
题意 S国有N个城市,编号从1到N.城市间用N-1条双向道路连接,满足从一个城市出发可以到达其它所有城市.每个城市信仰不同的宗教,如飞天面条神教.隐形独角兽教.绝地教都是常见的信仰. 为了方便,我们用 ...
- BZOJ 3531: [Sdoi2014]旅行 [树链剖分]
3531: [Sdoi2014]旅行 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 1685 Solved: 751[Submit][Status] ...
- BZOJ 3531 SDOI2014 旅行 树链剖分+线段树动态开点
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=3531 题意概述: 给出一棵N个点的树,树上的每个结点有一个颜色和权值,支持以下四种操作: ...
- BZOJ3531:[SDOI2014]旅行(树链剖分)
Description S国有N个城市,编号从1到N.城市间用N-1条双向道路连接,满足 从一个城市出发可以到达其它所有城市.每个城市信仰不同的宗教,如飞天面条神教.隐形独角兽教.绝地教都是常见的信仰 ...
随机推荐
- 20155323 2016-2017-2 《Java程序设计》第2周学习总结
20155323 2016-2017-2 <Java程序设计>第2周学习总结 教材学习内容总结 对象:对象是类的一个实例,有状态和行为. 类:类是一个模板,它描述一类对象的行为和状态. 第 ...
- 打豪车应用:uber详细攻略(附100元优步uber优惠码、uber优惠券、优步优惠码、优步优惠券)
在嘀嘀打车和快的打车交战热闹的时候,美国的打车应用uber进入中国.与在美国以个人司机注册做 Uber 司机为主的模式不同,Uber 在中国采用与租车公司合作.由租车公司提供车辆和司机的模式,同时中文 ...
- (ex)Lucas总结
(ex)Lucas总结 普通Lucas 求 \[ C_n^m\;mod\;p \] 其中\(n,m,p\leq 10^5\)其中\(p\)为质数 公式不难背,那就直接背吧... \[ C_n^m\;m ...
- Yii2.0 技巧总结
View部分 1. 使用ActiveField中的hint生成提示文字 <?= $form->field($model, 'freightAddedFee')->textInput( ...
- C#--Switch Case语句的返回
C#中switch case语句的返回不只是用break关键字,break语句是用来阻止贯穿的最常见的方式.也可以用其他语句来替代它.如下面代码所示 static int Main(string[] ...
- selenium自动化之定位多个元素
前面我们讲的都是如何定位单个元素,下面讲下怎么去定位多个元素,并且输出文本. 以百度为例:获取标红的这一组元素的文本 这里我用到的是xpath来定位的://div[@id="u1" ...
- 百度地图之自动提示--autoComplete
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- MapReduce和yarn
1.Mapreduce是什么? Mapreduce是一个分布式运算程序的编程框架,是用户开发“基于hadoop的数据分析应用”的核心框架: Mapreduce核心功能是将用户编写的业务逻辑代码和自带默 ...
- 剑指offer-二维数组中的查找01
题目描述 在一个二维数组中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序.请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数 ...
- pyextend库-merge可迭代对象合并函数
pyextend - python extend lib merge (iterable1, *args) 参数: iterable1: 实现 __iter__的可迭代对象, 如 str, tupl ...