【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 ...
随机推荐
- 20155339平措卓玛 Exp1 PC平台逆向破解(5)M
20155339平措卓玛 Exp1 PC平台逆向破解(5)M 实践内容 手工修改可执行文件,改变程序执行流程,直接跳转到getShell函数. 利用foo函数的Bof漏洞,构造一个攻击输入字符串,覆盖 ...
- sinopia 搭建记录
最近公司有个问题,一些公共部分每次都要手动发送,放到 git 上涉及到父子 git 问题,现在就想在内部搭建一个 npm,涉及到公共模块了就直接 npm update 更新一下.找到了 sinopia ...
- 【LG4248】[AHOI2013]差异
[LG4248][AHOI2013]差异 题面 洛谷 题解 后缀数组版做法戳我 我们将原串\(reverse\),根据后缀自动机的性质,两个后缀的\(lcp\)一定是我们在反串后两个前缀的\(lca\ ...
- Wannafly挑战赛26-F-msc的棋盘[最小割转化dp]
题意 一个大小为 \(n*m\) 的棋盘,知道每一列放了多少棋子,求有多少摆放方案满足要求. \(n,m\leq 50\) . 分析 如果是求是否有方案的话可以考虑网络流,行列连边,列容量为 \(b_ ...
- 基于spring的redisTemplate的缓存工具类
pom.xml文件添加 <!-- config redis data and client jar --><dependency> <groupId>org.spr ...
- 微信小程序实现各种特效实例
写在前面 最近在负责一个微信小程序的前端以及前后端接口的对接的项目,整体上所有页面的布局我都已经搭建完成,里面有一些常用的特效,总结一下,希望对大家和我都能有所帮助 实例1:滚动tab选项卡 先看一下 ...
- Boyer and Moore Fast majority vote algorithm(快速选举算法)
问题来来自于leetcode上的一道题目,https://leetcode.com/problems/majority-element/,大意是是找出一个数组中,出现次数超过一个半的数字,要求是O(n ...
- identityServer4 中的概念(Scope,claim)
在IdentityServer中好多地方出现这几个词,这单词的解释也有好多大神解释过: chaim: ASP.NET Core 之 Identity 入门(一),这个是asp.net identity ...
- win7+opencv3.0.0+vs2010 安装及配置
最近看<学习opencv>,想要跑人脸识别的例子,于是先配环境吧. 1. opencv下载: 具体下载地址,http://opencv.org/,官网太慢,百度网盘的资源链接:http: ...
- DataGridView显示行号-RowPostPaint
DataGridView控件在显示数据时,我们有时候需要显示行号,以便检索查看方便使用. 但DataGridView默认没有设置显示行号的属性. 此时我们只要在DataGridView的RowPost ...