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条双向道路连接,满足 从一个城市出发可以到达其它所有城市.每个城市信仰不同的宗教,如飞天面条神教.隐形独角兽教.绝地教都是常见的信仰 ...
随机推荐
- day 14 元组
1. 使用场景? # 列表list 数据类型相同, #rwx文件 100个人的名字, # 用字典 dict ['dɪkt] 很多信息描述1个人, # tuple [ˈtʌpəl] #只读文件 不能修改 ...
- day 12 文件操作
1.文件定位读写 f.seek(2,0) ##### f.seek(2,0) In [4]: f = open("test.py","r") In [5]: ...
- Nginx入门篇(五)之LNMP环境应用
一.LNMP组合工作原理 (1)用户通过浏览器输入域名请求Nginx web服务: (2)Nginx对请求的资源进行判断,如果是静态资源,则由Nginx返回给用户:如果是动态请求(.php文件),那么 ...
- MySQL入门篇(二)之常见命令管理
一.SQL结构化查询语言 SQL,英文全称Structured Query Language,中文意思是结构化查询语言.它是一种对关系数据库中的数据进行定义和操作的语言方法,是大多数关系数据库管理系统 ...
- zedboard学习(1)OLED驱动显示图像
1. 干点啥?驱动一下上面的屏吧 2. 找个代码研究一下,cat命令用于读取文件(普通文件或设备文件)的内容并进行输出.据说板子已经做好OLED的驱动了,驱动映射为/dev/zed_oled,所以直接 ...
- 【JUC源码解析】Semaphore
简介 Semaphore(信号量),概念上讲,一个信号量持有一组许可(permits). 概述 线程可调用它的acquire()方法获取一个许可,不成功则阻塞:调用release()方法来归还一个许可 ...
- 微软office web apps 服务器搭建之在线文档预览(二)
上一篇文章已经介绍了整个安装过程了.只要在浏览器中输入文档转换server的ip,会自动跳转,出现如下页面. 那么就可以实现本地文档预览了,你可以试试.(注意:是本地哦,路径不要写错,类似“\\fil ...
- iOS 上架的坑
有3D-touch机型的坑 昨天在上线的时候遇到了一个坑,最后导致的结果是找了好几个小时,直接到半夜才能上线. 入正题: 坑是:项目运行在456上没什么问题,但是在6S以上的机型就有点击事件不响应的情 ...
- Android 测试 之MonkeyRunner
一.什么是MonkeyRunner monkeyrunner工具提供了一个API,使用此API写出的程序可以在Android代码之外控制Android设备和模拟器.通过monkeyrunner,您可以 ...
- spring 属性文件加载接口---PropertySourceLoader
org.springframework.boot.config Interface PropertySourceLoader 实现类: PropertiesPropertySourceLoader, ...