问题描述

LG1505


题解

边化点权。

超级多操作的树剖板子...

以后就拿这个当树剖板子复习吧...


\(\mathrm{Code}\)

#include<bits/stdc++.h>
using namespace std; template <typename Tp>
void read(Tp &x){
x=0;char ch=1;int fh;
while(ch!='-'&&(ch>'9'||ch<'0')) ch=getchar();
if(ch=='-') ch=getchar(),fh=-1;
else fh=1;
while(ch>='0'&&ch<='9') x=(x<<1)+(x<<3)+ch-'0',ch=getchar();
x*=fh;
} template <typename Tp>
void fr(Tp &x){
char ch=1;
while(ch!='C'&&ch!='N'&&ch!='S'&&ch!='M') ch=getchar();
if(ch=='M'){
ch=1;while(ch!='A'&&ch!='I') ch=getchar();
}
if(ch=='C') x=1;
else if(ch=='N') x=2;
else if(ch=='S') x=3;
else if(ch=='A') x=4;
else x=5;
} const int maxn=40007;
const int INF=0x3f3f3f3f; int n;
int Head[maxn],to[maxn],Next[maxn],tot=1,w[maxn]; int size[maxn],fa[maxn],dep[maxn];
int New[maxn],pre[maxn],ind,top[maxn];
int son[maxn]; //edge id i -> 2*i-1,2*i void add(int x,int y,int z){
to[++tot]=y,Next[tot]=Head[x],Head[x]=tot,w[tot]=z;
} void dfs1(int x,int f,int dp){
size[x]=1,fa[x]=f,dep[x]=dp;
int mxx=-1;
for(int i=Head[x];i;i=Next[i]){
int y=to[i];
if(y==f) continue;
dfs1(y,x,dp+1);
size[x]+=size[y];
if(size[y]>mxx) mxx=size[y],son[x]=y;
}
} void dfs2(int x,int tp){
New[x]=++ind,pre[ind]=x,top[x]=tp;
if(!son[x]) return;
dfs2(son[x],tp);
for(int i=Head[x];i;i=Next[i]){
int y=to[i];
if(y==fa[x]||y==son[x]) continue;
dfs2(y,y);
}
} int val[maxn],f[maxn]; void preprocess(){
for(int i=2;i<=tot;i+=2){//错误笔记:tot一开始等于1,则第一条边从2开始
int x=to[i xor 1],y=to[i];
if(dep[x]>dep[y]) val[x]=w[i],f[i]=f[i xor 1]=x;//错误笔记:边化点权,要记录每个边化到哪个点上了。
else val[y]=w[i],f[i]=f[i xor 1]=y;
}
} #define lfc (x<<1)
#define rgc ((x<<1)|1)
#define mid ((l+r)>>1) int mx[maxn<<1],mi[maxn<<1],sum[maxn<<1];
int lazy[maxn<<1]; void pushup(int x){
mx[x]=max(mx[lfc],mx[rgc]);
mi[x]=min(mi[lfc],mi[rgc]);
sum[x]=sum[lfc]+sum[rgc];
} void pushdown(int x){
if(!lazy[x]) return;
lazy[lfc]^=1,lazy[rgc]^=1;
sum[lfc]=-sum[lfc],sum[rgc]=-sum[rgc];
int lf=mx[lfc],rg=mx[rgc];
mx[lfc]=-mi[lfc],mx[rgc]=-mi[rgc];
mi[lfc]=-lf,mi[rgc]=-rg;
lazy[x]=0;//错误笔记:lazy标记有没有清空
} void build(int x,int l,int r){
if(l==r){
mx[x]=mi[x]=sum[x]=val[pre[l]];
return;
}
build(lfc,l,mid);build(rgc,mid+1,r);
pushup(x);
} int L,R,need; void dd_change(int x,int l,int r){
if(l==r&&L==l){
sum[x]=mx[x]=mi[x]=need;return;
}
pushdown(x);
if(L<=mid) dd_change(lfc,l,mid);
else dd_change(rgc,mid+1,r);
pushup(x);
} void qj_change(int x,int l,int r){
if(l>R||r<L) return;
if(L<=l&&r<=R){
lazy[x]^=1;int temp=mx[x];
sum[x]=-sum[x],mx[x]=-mi[x],mi[x]=-temp;
return;
}
pushdown(x);
qj_change(lfc,l,mid);qj_change(rgc,mid+1,r);
pushup(x);
} int sum_query(int x,int l,int r){
if(l>R||r<L) return 0;
if(L<=l&&r<=R) return sum[x];
pushdown(x);
return sum_query(lfc,l,mid)+sum_query(rgc,mid+1,r);
} int max_query(int x,int l,int r){
if(l>R||r<L) return -INF;
if(L<=l&&r<=R) return mx[x];
pushdown(x);
return max(max_query(lfc,l,mid),max_query(rgc,mid+1,r));
} int min_query(int x,int l,int r){
if(l>R||r<L) return INF;
if(L<=l&&r<=R) return mi[x];
pushdown(x);
return min(min_query(lfc,l,mid),min_query(rgc,mid+1,r));
} int T,op; void cz1(){
int x;
read(x);read(need);
x=New[f[x<<1]],L=x;//错误笔记:双向存边,在数组中编号要*2
dd_change(1,1,n);
} void cz2(){
int x,y;
read(x);read(y);
++x,++y;
while(top[x]!=top[y]){
if(dep[top[x]]<dep[top[y]]) swap(x,y);
L=New[top[x]],R=New[x];//错误笔记:写作L=New[x],R=New[y]
qj_change(1,1,n);
x=fa[top[x]];
}
if(dep[x]>dep[y]) swap(x,y);
L=New[x]+1,R=New[y];
if(L<=R) qj_change(1,1,n);
} void cz3(){
int x,y,res=0;
read(x);read(y);
++x,++y;
while(top[x]!=top[y]){
if(dep[top[x]]<dep[top[y]]) swap(x,y);
L=New[top[x]],R=New[x];
res+=sum_query(1,1,n);
x=fa[top[x]];
}
if(dep[x]>dep[y]) swap(x,y);
L=New[x]+1,R=New[y];
if(L<=R) res+=sum_query(1,1,n);
printf("%d\n",res);
} void cz4(){
int x,y,res=-INF;
read(x);read(y);
++x,++y;
while(top[x]!=top[y]){
if(dep[top[x]]<dep[top[y]]) swap(x,y);
L=New[top[x]],R=New[x];
res=max(res,max_query(1,1,n));
x=fa[top[x]];
}
if(dep[x]>dep[y]) swap(x,y);
L=New[x]+1,R=New[y];
if(L<=R) res=max(res,max_query(1,1,n));
printf("%d\n",res);
} void cz5(){
int x,y,res=INF;
read(x);read(y);
++x,++y;
while(top[x]!=top[y]){
if(dep[top[x]]<dep[top[y]]) swap(x,y);
L=New[top[x]],R=New[x];
res=min(res,min_query(1,1,n));
x=fa[top[x]];
}
if(dep[x]>dep[y]) swap(x,y);
L=New[x]+1,R=New[y];
if(L<=R) res=min(res,min_query(1,1,n));
printf("%d\n",res);
} int main(){
#ifndef ONLINE_JUDGE
freopen("travel.in","r",stdin);
#endif
read(n);
for(int i=1,x,y,z;i<n;i++){
read(x);read(y);read(z);
++x,++y;
add(x,y,z);add(y,x,z);
}
dfs1(1,0,1);dfs2(1,1);
preprocess();build(1,1,n);
read(T);
while(T--){
fr(op);
if(op==1) cz1();
else if(op==2) cz2();
else if(op==3) cz3();
else if(op==4) cz4();
else cz5();
}
return 0;
}

LG1505 [国家集训队]旅游 树链剖分的更多相关文章

  1. 洛谷 P1505 [国家集训队]旅游 树链剖分

    目录 题面 题目链接 题目描述 输入输出格式 输入格式 输出格式 输入输出样例 输入样例: 输出样例: 说明 思路 AC代码 总结 题面 题目链接 P1505 [国家集训队]旅游 题目描述 Ray 乐 ...

  2. LUOGU P1505 [国家集训队]旅游 (树链剖分+线段树)

    传送门 解题思路 快被调死的码农题,,,其实就是一个边权下放到点权的线段树+树剖. #include<iostream> #include<cstdio> #include&l ...

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

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

  4. BZOJ2157旅游——树链剖分+线段树

    题目描述 Ray 乐忠于旅游,这次他来到了T 城.T 城是一个水上城市,一共有 N 个景点,有些景点之间会用一座桥连接.为了方便游客到达每个景点但又为了节约成本,T 城的任意两个景点之间有且只有一条路 ...

  5. BZOJ3999:[TJOI2015]旅游(树链剖分)

    Description 为了提高智商,ZJY准备去往一个新世界去旅游.这个世界的城市布局像一棵树.每两座城市之间只有一条路径可 以互达.每座城市都有一种宝石,有一定的价格.ZJY为了赚取最高利益,她会 ...

  6. BZOJ2157: 旅游 树链剖分 线段树

    http://www.lydsy.com/JudgeOnline/problem.php?id=2157   在对树中数据进行改动的时候需要很多pushdown(具体操作见代码),不然会wa,大概原因 ...

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

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

  8. 【BZOJ2157】旅游 树链剖分+线段树

    [BZOJ2157]旅游 Description Ray 乐忠于旅游,这次他来到了T 城.T 城是一个水上城市,一共有 N 个景点,有些景点之间会用一座桥连接.为了方便游客到达每个景点但又为了节约成本 ...

  9. P1505 [国家集训队]旅游[树剖]

    题目描述 Ray 乐忠于旅游,这次他来到了T 城.T 城是一个水上城市,一共有 N 个景点,有些景点之间会用一座桥连接.为了方便游客到达每个景点但又为了节约成本,T 城的任意两个景点之间有且只有一条路 ...

随机推荐

  1. Linux 小工具

    1. 截图工具 shutter 安装 sudo add-apt-repository ppa:shutter/ppa sudo apt-get update sudo apt-get install ...

  2. 正确使用Spring Data JPA规范

    在优锐课的学习分享中探讨了关于,Spring Data JPA的创建主要是为了通过按方法名称生成查询来轻松创建查询. 但是,有时我们需要创建复杂的查询,而无法利用查询生成器.码了很多知识笔记分享给大家 ...

  3. dell服务器已有阵列新增的磁盘无法识别显示外来

    问题描述: 今天遇到个插入新硬盘显示外来盘,然后不可用,然后电话问了一下戴尔的工程师 说需要清除一下原来磁盘的阵列信息之类的,才能识别到,这里就做一个笔记记录一下,顺便分享给有需要的朋友! 解决方法: ...

  4. IT兄弟连 Java语法教程 Java语法基础 经典面试题

    1.Java语言中有几种基本类型?分别是什么?请详细说明每种类型的范围以及所占的空间大小? Java语言中有8中基本类型,分别是代表整形的byte.short.int和long,代表浮点型的float ...

  5. 前端笔记之Vue(四)UI组件库&Vuex&虚拟服务器初识

    一.日历组件 new Date()的月份是从0开始的. 下面表达式是:2018年6月1日 new Date(2018, 5, 1); 下面表达式是:2018年5月1日 new Date(2018, 4 ...

  6. 05爬虫-requests模块基础(2)

    今日重点: 1.代理服务器的设置 2.模拟登陆过验证码(静态验证码) 3.cookie与session 4.线程池 1.代理服务器的设置 有时候使用同一个IP去爬取同一个网站,久了之后会被该网站服务器 ...

  7. pytest框架之parametries数据驱动参数化

    在测试用例的前面加上:@pytest.mark.parametrize('参数名', 列表数据) 参数名:用来接收每一项数据,并作为测试用例的参数 列表参数:一组测试数据(元组.列表.字典) 方式一: ...

  8. 创 PHP RSA2 签名算法

        什么是RSA2 ? RSA2 是在原来SHA1WithRSA签名算法的基础上,新增了支持SHA256WithRSA的签名算法. 该算法比SHA1WithRSA有更强的安全能力. 为了您的应用安 ...

  9. 恢复Chrome 78以上版本的地址栏https和www显示

    Google在Chrome不知道是脑子抽抽还是怎么回事,非要把https://www从地址栏中隐藏掉. htttps://www.pool.ntp.org就给你显示个pool.ntp.org,这分明就 ...

  10. Disruptor系列(二)— disruptor使用

    本文译自Dirsruptor在github上的wiki中文章:Getting Started 获取Disruptor Disruptor jar包可以从maven仓库mvnrepository获取,可 ...