【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的更多相关文章
- 【数据结构】B-Tree, B+Tree, B*树介绍 转
[数据结构]B-Tree, B+Tree, B*树介绍 [摘要] 最近在看Mysql的存储引擎中索引的优化,神马是索引,支持啥索引.全是浮云,目前Mysql的MyISAM和InnoDB都支持B-Tre ...
- P3690 【模板】Link Cut Tree (动态树)
P3690 [模板]Link Cut Tree (动态树) 认父不认子的lct 注意:不 要 把 $fa[x]$和$nrt(x)$ 混 在 一 起 ! #include<cstdio> v ...
- LG3690 【模板】Link Cut Tree (动态树)
题意 给定n个点以及每个点的权值,要你处理接下来的m个操作.操作有4种.操作从0到3编号.点从1到n编号. 0:后接两个整数(x,y),代表询问从x到y的路径上的点的权值的xor和.保证x到y是联通的 ...
- AC日记——【模板】Link Cut Tree 洛谷 P3690
[模板]Link Cut Tree 思路: LCT模板: 代码: #include <bits/stdc++.h> using namespace std; #define maxn 30 ...
- LG3690 【模板】Link Cut Tree 和 SDOI2008 洞穴勘测
UPD:更新了写法. [模板]Link Cut Tree 给定n个点以及每个点的权值,要你处理接下来的m个操作.操作有4种.操作从0到3编号.点从1到n编号. 后接两个整数(x,y),代表询问从x到y ...
- (RE) luogu P3690 【模板】Link Cut Tree
二次联通门 : luogu P3690 [模板]Link Cut Tree 莫名RE第8个点....如果有dalao帮忙查错的话万分感激 #include <cstdio> #includ ...
- LuoguP3690 【模板】Link Cut Tree (动态树) LCT模板
P3690 [模板]Link Cut Tree (动态树) 题目背景 动态树 题目描述 给定n个点以及每个点的权值,要你处理接下来的m个操作.操作有4种.操作从0到3编号.点从1到n编号. 0:后接两 ...
- 【LeetCode】199. Binary Tree Right Side View 解题报告(Python)
[LeetCode]199. Binary Tree Right Side View 解题报告(Python) 标签: LeetCode 题目地址:https://leetcode.com/probl ...
- 【数据结构】B-Tree, B+Tree, B*树介绍
[摘要] 最近在看Mysql的存储引擎中索引的优化,神马是索引,支持啥索引.全是浮云,目前Mysql的MyISAM和InnoDB都支持B-Tree索引,InnoDB还支持B+Tree索引,Memory ...
随机推荐
- C# Test Encryption and Decryption
public MainWindow() { InitializeComponent(); Title = getUUID(); string s= httpGet("http://220.1 ...
- 20155204 王昊《网络对抗技术》EXP1 PC平台逆向破解
20155204 王昊<网络对抗技术>EXP1 PC平台逆向破解 (一)实验内容 一.掌握NOP.JNE.JE.JMP.CMP汇编指令的机器码 NOP:NOP指令即"空指令&qu ...
- 20155216 Exp5 MSF基础应用
Exp5 MSF基础应用 基础问题回答 1.用自己的话解释什么是exploit,payload,encode? exploit : Exploit的英文意思就是利用,在做攻击时,通常称为漏洞利用. 一 ...
- mfc 动态为控件添加事件2
重载窗口过程 为动态控件绑定事件 一.重载窗口过程处理函数 CWnd::WindowProc virtual LRESULT WindowProc( UINT message, WPARAM wPar ...
- xgboost学习与总结
最近在研究xgboost,把一些xgboost的知识总结一下.这里只是把相关资源作总结,原创的东西不多. 原理 xgboost的原理首先看xgboost的作者陈天奇的ppt 英文不太好的同学可以看看这 ...
- python list的一个面试题
面试题''' 一个list,里面的数字偶数在左边,奇数在右边,不借助其他列表 ''' def userlist(add_list): if type(add_list)==list: if len(a ...
- ANSYS渡槽槽身动水压力的施加(2)——U型渡槽
U型渡槽动水压力荷载施加命令及说明 程序中需要用到ANSYS重启动,因为需提取前一步加速度结果以施加部分动水压力: 默认Y方向为重力方向,X方向为横槽向,Z方向为纵槽向: 需准备地震波文件: 需先将槽 ...
- Ubuntu侧边任务栏自动隐藏
设置>>Dock>>{自动隐藏Dock}选项打开
- 金蝶盘点机PDA仓库条码管理:仓库如何盘点
1.1. 仓库盘点 传统的仓库盘点,需要人工手工抄写盘点单,时候再去电脑上一行行的录入盘点单,操作非常耗时费力,往往需要盘点好几天,最终盘点效果还不好,在抄写过程中容易出现错误,从而造成盘点结果不准确 ...
- L2-031 深入虎穴(BFS)
著名的王牌间谍 007 需要执行一次任务,获取敌方的机密情报.已知情报藏在一个地下迷宫里,迷宫只有一个入口,里面有很多条通路,每条路通向一扇门.每一扇门背后或者是一个房间,或者又有很多条路,同样是每条 ...