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条双向道路连接,满足 从一个城市出发可以到达其它所有城市.每个城市信仰不同的宗教,如飞天面条神教.隐形独角兽教.绝地教都是常见的信仰 ...
随机推荐
- 2017-2018-1 20155323《信息安全技术》实验二 Windows口令破解
2017-2018-1 20155323<信息安全技术>实验二 Windows口令破解 实验目的 了解Windows口令破解原理 对信息安全有直观感性认识 能够运用工具实现口令破解 系统环 ...
- day 11 名片管理系统
1 思路 #名片1 名片2 {"name":"alex","age":18,"QQ":12123} {"nam ...
- 【LG5022】[NOIP2018]旅行
[LG5022][NOIP2018]旅行 题面 洛谷 题解 首先考虑一棵树的部分分怎么打 直接从根节点开始\(dfs\),依次选择编号最小的儿子即可 而此题是一个基环树 怎么办呢? 可以断掉环上的一条 ...
- underscore.js 分析 第四天
查看underscore包含多少属性和方法 通过阅读JavaScript 获取对象的键的数组 var a = _; var arr = Object.keys(a); console.log(arr) ...
- Drupal8 Console 命令行工具
转载:https://yplam.com/post/79 Drupal Console 是面向Drupal 8 的一套命令行工具,用来生成Drupal 8模板代码,并且可以跟Drupal 8应用进行交 ...
- Yii2 Gridview 动态显示行或列和action列
我们知道Yii中的GridView组件是非常好用的. 某些情况要动态显示某列,这时候就要用到visible属性 'propString' => ['attribute' => 'prope ...
- asp.net core webapi项目配置全局路由
0.目录 整体架构目录:ASP.NET Core分布式项目实战-目录 一.前言 在开发项目的过程中,我新创建了一个controller,发现vs会给我们直接在controller头添加前缀,比如[Ro ...
- 使用 AFNetworking做过断点续传吗?
断点续传的主要思路: 检查服务器文件信息 检查本地文件 如果比服务器文件小, 断点续传, 利用 HTTP 请求头的 content-range实现断点续传(如果content-range不存在就取Co ...
- C# 多线程的等待所有线程结束的一个问题
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 3 ...
- Docker--从安装到搭建环境
docker 1. ubuntu下安装docker 安装docker有两种方法: 一种是用官方的bash脚本一键安装. 直接一条命令就解决了: $ curl -sSL https://get.dock ...