Portal --> CC Batman and Tree

Solution

  一开始看到很懵。。感觉无从下手(因为自己太菜了qwq)

​  膜拜了题解之后发现好像并没有想象的那么复杂qwq

​  其实冷静下来考虑dp,用\(f[i]\)表示当前在\(i\)的最大能量值,然后对于一个从\(x\)到\(y\)的强盗,考虑找一条路径满足\(x\)到\(y\)的简单路径是其子路径,那么我们就可以用满足条件的路径的端点\(f\)值的最大值来更新走到的另一个端点处的新\(f\)值

​  将dfs序处理出来,不难发现满足条件的路径的端点对应的应该是几段区间,具体一点就是(默认\(dep[x]<=dep[y]\)):

(1)\(x\)是\(y\)的祖先,此时记\(dw\)为满足\(y\in subtree(dw)\)且\(dw\in son(x)\)的节点,那么可以选路径的的端点应该一个在区间\([1,st[dw]]\cup[ed[dw]+1,n]\)内,一个在\([st[y],ed[y]]\)内

(2)\(x\)不是\(y\)的祖先,那么此时可以选路径的端点应该一个在\([st[x],ed[x]]\),一个在\([st[y],ed[y]]\)内

  那么直接线段树维护一下就好了,实现一个区间取max和区间查询max即可(吉老师线段树)

  

Code

#include<iostream>
#include<cstdio>
#include<cstring>
#define ll long long
using namespace std;
const int N=4e5+10,TOP=20;
const ll inf=1LL<<60;
struct xxx{
int y,nxt;
}a[N*2];
int h[N],lis[N],dep[N];
int st[N],ed[N],f[N][TOP+1];
int n,m,tot,dfn_t,dfn_t1;
int S,P,T;
namespace Seg{/*{{{*/
const int N=::N*4;
int ch[N][2];
ll tag[N],mx[N],smx[N],mn[N],smn[N];
int n,tot;
void pushup(int x){
if (mx[ch[x][0]]==mx[ch[x][1]]){
mx[x]=mx[ch[x][0]];
smx[x]=max(smx[ch[x][0]],smx[ch[x][1]]);
}
else{
int lw,up;
if (mx[ch[x][0]]>mx[ch[x][1]]) up=0,lw=1;
else up=1,lw=0;
mx[x]=mx[ch[x][up]];
smx[x]=max(smx[ch[x][up]],mx[ch[x][lw]]);
} if (mn[ch[x][0]]==mn[ch[x][1]]){
mn[x]=mn[ch[x][0]];
smn[x]=min(smn[ch[x][0]],smn[ch[x][1]]);
}
else{
int lw,up;
if (mn[ch[x][0]]<mn[ch[x][1]]) lw=0,up=1;
else lw=1,up=0;
mn[x]=mn[ch[x][lw]];
smn[x]=min(smn[ch[x][lw]],mn[ch[x][up]]);
}
}
void _build(int x,int l,int r){
smx[x]=-inf; smn[x]=inf; tag[x]=0;
if (l==r){mx[x]=mn[x]=(::lis[l]==S?P:-inf);return;}
int mid=l+r>>1;
ch[x][0]=++tot; _build(ch[x][0],l,mid);
ch[x][1]=++tot; _build(ch[x][1],mid+1,r);
pushup(x);
}
void build(int _n){n=_n; tot=1; _build(1,1,n);}
void give_mxtag(int x,ll delta){
mn[x]=delta;
mx[x]=max(mx[x],delta);
tag[x]=max(tag[x],delta);
if (mn[x]==mx[x])
smn[x]=inf,smx[x]=-inf;
else
smx[x]=max(smx[x],delta);
}
void downtag(int x){
if (!tag[x]) return;
if (ch[x][0])
if (mn[ch[x][0]]<mn[x]&&mn[x]<smn[ch[x][0]])
give_mxtag(ch[x][0],tag[x]);
if (ch[x][1])
if (mn[ch[x][1]]<mn[x]&&mn[x]<smn[ch[x][1]])
give_mxtag(ch[x][1],tag[x]);
tag[x]=0;
}
void _update(int x,int l,int r,int lx,int rx,ll delta){
if (mn[x]>=delta) return;
if (l<=lx&&rx<=r&&delta<smn[x]){
give_mxtag(x,delta);
return;
}
downtag(x);
int mid=lx+rx>>1;
if (r<=mid) _update(ch[x][0],l,r,lx,mid,delta);
else if (l>mid) _update(ch[x][1],l,r,mid+1,rx,delta);
else{
_update(ch[x][0],l,mid,lx,mid,delta);
_update(ch[x][1],mid+1,r,mid+1,rx,delta);
}
pushup(x);
}
void update(int l,int r,ll delta){if (l<=r) _update(1,l,r,1,n,delta);}
ll _query(int x,int l,int r,int lx,int rx){
if (l<=lx&&rx<=r) return mx[x];
downtag(x);
int mid=lx+rx>>1;
if (r<=mid) return _query(ch[x][0],l,r,lx,mid);
else if (l>mid) return _query(ch[x][1],l,r,mid+1,rx);
else
return max(_query(ch[x][0],l,mid,lx,mid),_query(ch[x][1],mid+1,r,mid+1,rx));
}
ll query(int l,int r){return l>r?-inf:_query(1,l,r,1,n);}
void _debug(int x,int lx,int rx){
if (lx==rx){printf("%lld ",mx[x]); return;}
downtag(x);
int mid=lx+rx>>1;
_debug(ch[x][0],lx,mid);
_debug(ch[x][1],mid+1,rx);
}
void debug(){_debug(1,1,n);}
}/*}}}*/
void add(int x,int y){a[++tot].y=y; a[tot].nxt=h[x]; h[x]=tot;}
void dfs(int fa,int x,int d){
int u;
lis[++dfn_t]=x;
st[x]=dfn_t; dep[x]=d;
f[x][0]=fa;
for (int i=1;i<=TOP;++i) f[x][i]=f[f[x][i-1]][i-1];
for (int i=h[x];i!=-1;i=a[i].nxt){
u=a[i].y;
if (u==fa) continue;
dfs(x,u,d+1);
}
ed[x]=dfn_t;
}
int jump(int x,int d){
if (d==0) return x;
for (int i=0;i<=TOP;++i)
if (d>>i&1) x=f[x][i];
return x;
}
void debug(){
for (int i=1;i<=n;++i) printf("%lld ",Seg::query(i,i)); printf("\n");
}
void modify(int x,int y,int r,int t){
ll tmp1,tmp2;
int dw;
//dep[x]<dep[y]
if (dep[x]>dep[y]) swap(x,y);
if (st[x]<=st[y]&&st[y]<=ed[x]){
dw=jump(y,dep[y]-dep[x]-1);
tmp1=max(Seg::query(1,st[dw]-1),Seg::query(ed[dw]+1,n));
tmp2=Seg::query(st[y],ed[y]); if (tmp2>r){
Seg::update(1,st[dw]-1,tmp2+t);
Seg::update(ed[dw]+1,n,tmp2+t);
}
if (tmp1>r)
Seg::update(st[y],ed[y],tmp1+t);
}
else{
tmp1=Seg::query(st[x],ed[x]);
tmp2=Seg::query(st[y],ed[y]); if (tmp2>r)
Seg::update(st[x],ed[x],tmp2+t);
if (tmp1>r)
Seg::update(st[y],ed[y],tmp1+t);
}
} int main(){
#ifndef ONLINE_JUDGE
freopen("a.in","r",stdin);
#endif
int x,y,r,t;
scanf("%d",&T);
for (int o=1;o<=T;++o){
scanf("%d%d%d",&n,&S,&P);
memset(h,-1,sizeof(h));
tot=0;
for (int i=1;i<n;++i){
scanf("%d%d",&x,&y);
add(x,y); add(y,x);
}
dfn_t=0;
dfs(0,1,1);
Seg::build(n);
scanf("%d",&m);
for (int i=1;i<=m;++i){
scanf("%d%d%d%d",&x,&y,&r,&t);
modify(x,y,r,t);
}
printf("%lld\n",Seg::mx[1]);
}
}

【CC】Batman and Tree的更多相关文章

  1. 【数据结构】B-Tree, B+Tree, B*树介绍 转

    [数据结构]B-Tree, B+Tree, B*树介绍 [摘要] 最近在看Mysql的存储引擎中索引的优化,神马是索引,支持啥索引.全是浮云,目前Mysql的MyISAM和InnoDB都支持B-Tre ...

  2. P3690 【模板】Link Cut Tree (动态树)

    P3690 [模板]Link Cut Tree (动态树) 认父不认子的lct 注意:不 要 把 $fa[x]$和$nrt(x)$ 混 在 一 起 ! #include<cstdio> v ...

  3. LG3690 【模板】Link Cut Tree (动态树)

    题意 给定n个点以及每个点的权值,要你处理接下来的m个操作.操作有4种.操作从0到3编号.点从1到n编号. 0:后接两个整数(x,y),代表询问从x到y的路径上的点的权值的xor和.保证x到y是联通的 ...

  4. AC日记——【模板】Link Cut Tree 洛谷 P3690

    [模板]Link Cut Tree 思路: LCT模板: 代码: #include <bits/stdc++.h> using namespace std; #define maxn 30 ...

  5. LG3690 【模板】Link Cut Tree 和 SDOI2008 洞穴勘测

    UPD:更新了写法. [模板]Link Cut Tree 给定n个点以及每个点的权值,要你处理接下来的m个操作.操作有4种.操作从0到3编号.点从1到n编号. 后接两个整数(x,y),代表询问从x到y ...

  6. (RE) luogu P3690 【模板】Link Cut Tree

    二次联通门 : luogu P3690 [模板]Link Cut Tree 莫名RE第8个点....如果有dalao帮忙查错的话万分感激 #include <cstdio> #includ ...

  7. LuoguP3690 【模板】Link Cut Tree (动态树) LCT模板

    P3690 [模板]Link Cut Tree (动态树) 题目背景 动态树 题目描述 给定n个点以及每个点的权值,要你处理接下来的m个操作.操作有4种.操作从0到3编号.点从1到n编号. 0:后接两 ...

  8. 【LeetCode】199. Binary Tree Right Side View 解题报告(Python)

    [LeetCode]199. Binary Tree Right Side View 解题报告(Python) 标签: LeetCode 题目地址:https://leetcode.com/probl ...

  9. 【数据结构】B-Tree, B+Tree, B*树介绍

    [摘要] 最近在看Mysql的存储引擎中索引的优化,神马是索引,支持啥索引.全是浮云,目前Mysql的MyISAM和InnoDB都支持B-Tree索引,InnoDB还支持B+Tree索引,Memory ...

随机推荐

  1. Hibernate一对多关联关系保存时的探究

    在以前使用hibernate时,经常对保存存在关联关系的对象时,不确定是否能保存成功.    因此,特意对一对多关系的2个对象进行实践. 一.pojo类和配置文件的准备         这里有一点提前 ...

  2. 【MEF】构建一个WPF版的ERP系统

    原文:[MEF]构建一个WPF版的ERP系统 引言 MEF是微软的一个扩展性框架,遵循某种约定将各个部件组合起来.而ERP系统的一大特点是模块化,它们两者的相性很好,用MEF构建一个ERP系统是相当合 ...

  3. MiZ702学习笔记10——文本实例化IP的方法

    之前,添加vivado自带IP的时候,都是以图形化的方式:一般是新建一个Block Design顶层文件,然后将图形化的ip贴到,Block Design中. 但是,在进行PL的开发过程中,有时不想使 ...

  4. 汇编 EBP ,ESP 寄存器

    知识点:  CALL框架  EBP寄存器 栈底指针  ESP寄存器 栈顶指针 一.EBP栈底指针 EBP是一个特殊的寄存器,通过EBP+偏移量 可以访问CALL里边的局部变量.它的低16位叫BP ...

  5. 51nod 小朋友的笑话

    链接 分析: 每次操作把以前没有出现这个数的设为1,有这个数的设为0.首先将当前区间设为1,考虑有set维护这个颜色出现的区间,然后把所有与当前区间相交的拿出来,修改为0. 复杂度?每次操作的线段只会 ...

  6. 阿里云centos系统中配置mysql,并远程连接到本地的navicat

    1.直接使用yum命令下载mysql5.6来进行安装是不能成功的,安装过程会有问题,这里我们需要使用rpm命令来先进下载.下载路径为:http://dev.mysql.com/get/mysql-co ...

  7. cbuild-一个创建和管理C++项目的工具

    cbuild-一个创建和管理C++项目的工具 介绍: 这是个人开发的一个管理C++项目的工具,用shell脚本编写. 可能会不定期更新,也欢迎大家一起完善. 当前开发版本0.5.各版本功能如下: ve ...

  8. 使用顽灯浏览器执行H5游戏辅助挂机

    前一篇<使用Fidder从安卓模拟器获取APP内H5游戏网址>我们获取到了APP内H5游戏的网址,那么接下来我们使用辅助工具做一些日常任务,如:每天晚上20点做副本,定时喊话,自动清理包裹 ...

  9. IOTA price analysis

    Iota coinchart Look at the trendline drawn in red color, at the very first beginning of this month, ...

  10. Celery基本使用

    Celery 什么是Celery? Celery是一种简单/高效/灵活的即插即用的分布式任务队列. Celery应用场景? 需要异步处理的任务,发邮件/发短信/上传等耗时的操作.最终到达提升用户体验的 ...