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. Metasploit简单应用

    什么是Metasploit Metasploit是一款开源的安全漏洞检测工具. 它可以帮助用户识别安全问题,验证漏洞的缓解措施,并对某些软件进行安全性评估,提供真正的安全风险情报.当我们第一次接触Me ...

  2. RegExp,实现匹配合法时间(24小时制)的正则表达式

    合法时间格式  00:00:00 - 23:59:59   格式分析:H + ":" + M + ":" + S   H-分析: 00:00:00 - 09:5 ...

  3. Spring Boot (十三): Spring Boot 小技巧

    一些 Spring Boot 小技巧.小知识点 初始化数据 我们在做测试的时候经常需要初始化导入一些数据,如何来处理呢?会有两种选择,一种是使用 Jpa,另外一种是 Spring JDBC .两种方式 ...

  4. JavaScript快速入门-实战(例子)

    1.模拟bootstrap中的模态框 效果图:(点我后,弹出对话框,最下面的内容可以看到,但是有一定的透明度.) 思路分析: 整体分为三层,最底层(点我),中间透明层(实现透明效果),最顶层(最新内容 ...

  5. Outlook2013修改数据文件默认存放目录

    转载 当使用outlook 2013新建Email账户的时候,其数据文件(.ost文件)总是被保存在C盘默认目录“C:\Users\用户名\AppData\Local\Microsoft\Outloo ...

  6. [转载]JVM 垃圾回收机制(Garbage Collection)

    相关算法: 引用计数法 引用可达法 尚学堂 参考:http://www.sxt.cn/Java_jQuery_in_action/Principle_and_algorithm_of_garbage_ ...

  7. 前后端同学必会的Linux基础命令

    无论是前端还是后端同学,一些常用的linux命令还是必须要掌握的.发布版本.查看日志等等都会用到.以下是我简单的总结了一些简单又常用的命令,欢迎大家补充.希望能帮助到大家 基础篇 1.进入目录 cd ...

  8. linux使用curl上传文件并且同时携带其它传递参数

    一般使用linux原生态的命令curl上传文件时命令如下 假如要上传文件是myfile.txt curl -F "file_name=@myfile.txt" -X POST &q ...

  9. Spring学习总结之高级装配

    1.  profile profile可以决定bean在什么环境下才被装配(开发环境.测试环境.线上环境等) @Profile(“dev”)可以用在class之前,也可以用在类之前(Spring3.2 ...

  10. 《Linux内核分析》第三周笔记 构造一个简单的Linux系统MenuOS

    构造一个简单的Linux系统MenuOS 一.linux内核源代码简介 三大法宝(存储程序计算机.函数调用堆栈.中断)和两把宝剑(中断上下文的切换:保存现场和恢复现场.进程上下文的切换) 1.在lin ...