洛谷 P3398 仓鼠找sugar —— 树链剖分
题目:https://www.luogu.org/problemnew/show/P3398
树链剖分一下,路径就变成线段树上的几个区间;
两条路径相交就是线段树上有区间相交,所以在相应位置打个标记,查询有无标记即可;
一开始是打1的标记,查询后就减去,查询 sum 是否为 0 即可;
然而这样写却全 WA 了...悲痛欲绝去看了 TJ ,模仿了其写法,回头再看发现是忘记写 pushdown ,而且 -1 的地方写成 0 了囧...
改掉就 A 了,这个做法完全没问题嘛!
代码如下:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int const maxn=1e5+;
int n,q,hd[maxn],ct,sum[maxn<<],tim,fa[maxn],lzy[maxn<<];
int dep[maxn],dfn[maxn],top[maxn],son[maxn],siz[maxn],id[maxn];
struct N{
int to,nxt;
N(int t=,int n=):to(t),nxt(n) {}
}ed[maxn<<];
void add(int x,int y){ed[++ct]=N(y,hd[x]); hd[x]=ct;}
void dfs(int x,int f)
{
dep[x]=dep[f]+; siz[x]=; fa[x]=f;
for(int i=hd[x],u;i;i=ed[i].nxt)
{
if((u=ed[i].to)==f)continue;
dfs(u,x); siz[x]+=siz[u];
if(siz[u]>siz[son[x]])son[x]=u;
}
}
void dfs2(int x)
{
dfn[x]=++tim; id[tim]=x;//
if(son[x])top[son[x]]=top[x],dfs2(son[x]);
for(int i=hd[x],u;i;i=ed[i].nxt)
{
if((u=ed[i].to)==fa[x]||u==son[x])continue;
top[u]=u; dfs2(u);
}
}
void pushup(int x){sum[x]=sum[x<<]+sum[x<<|];}
void pushdown(int x,int l,int r)
{
if(!lzy[x])return;
int ls=(x<<),rs=(x<<|),mid=((l+r)>>);
lzy[ls]+=lzy[x]; lzy[rs]+=lzy[x];
sum[ls]+=lzy[x]*(mid-l+); sum[rs]+=lzy[x]*(r-mid);
lzy[x]=;
}
void add(int x,int l,int r,int L,int R,int val)
{
if(l>=L&&r<=R){sum[x]+=val*(r-l+); lzy[x]+=val; return;}
pushdown(x,l,r);//
int mid=((l+r)>>);
if(mid>=L)add(x<<,l,mid,L,R,val);
if(mid<R)add(x<<|,mid+,r,L,R,val);
pushup(x);
}
int ask(int x,int l,int r,int L,int R)
{
if(l>=L&&r<=R)return sum[x];
pushdown(x,l,r);//
int ret=,mid=((l+r)>>);
if(mid>=L)ret+=ask(x<<,l,mid,L,R);
if(mid<R)ret+=ask(x<<|,mid+,r,L,R);
return ret;
}
void update(int x,int y,int val)
{
while(top[x]!=top[y])
{
if(dep[top[x]]<dep[top[y]])swap(x,y);
add(,,n,dfn[top[x]],dfn[x],val);
x=fa[top[x]];
}
if(dep[x]<dep[y])swap(x,y);
add(,,n,dfn[y],dfn[x],val);
}
bool query(int x,int y)
{
while(top[x]!=top[y])
{
if(dep[top[x]]<dep[top[y]])swap(x,y);
if(ask(,,n,dfn[top[x]],dfn[x])) return ;
x=fa[top[x]];
}
if(dep[x]<dep[y])swap(x,y);
return ask(,,n,dfn[y],dfn[x]);
}
int main()
{
scanf("%d%d",&n,&q);
for(int i=,x,y;i<n;i++)
{
scanf("%d%d",&x,&y);
add(x,y); add(y,x);
}
dfs(,); top[]=; dfs2();
for(int i=,a,b,c,d;i<=q;i++)
{
scanf("%d%d%d%d",&a,&b,&c,&d);
update(a,b,);
if(query(c,d))printf("Y\n");
else printf("N\n");
update(a,b,-);//!0
}
return ;
}
还有 TJ 写法,就是不删除了,打个 int 类型的标记,所以查询 max 即可。
代码如下:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int const maxn=1e5+;
int n,q,hd[maxn],ct,mx[maxn<<],tim,fa[maxn],lzy[maxn<<],tot;
int dep[maxn],dfn[maxn],top[maxn],son[maxn],siz[maxn],id[maxn];
struct N{
int to,nxt;
N(int t=,int n=):to(t),nxt(n) {}
}ed[maxn<<];
void add(int x,int y){ed[++ct]=N(y,hd[x]); hd[x]=ct;}
void dfs(int x,int f)
{
dep[x]=dep[f]+; siz[x]=; fa[x]=f;
for(int i=hd[x],u;i;i=ed[i].nxt)
{
if((u=ed[i].to)==f)continue;
dfs(u,x); siz[x]+=siz[u];
if(siz[u]>siz[son[x]])son[x]=u;
}
}
void dfs2(int x)
{
dfn[x]=++tim; id[tim]=x;//
if(son[x])top[son[x]]=top[x],dfs2(son[x]);
for(int i=hd[x],u;i;i=ed[i].nxt)
{
if((u=ed[i].to)==fa[x]||u==son[x])continue;
top[u]=u; dfs2(u);
}
}
void pushup(int x){mx[x]=max(mx[x<<],mx[x<<|]);}
void pushdown(int x)
{
if(!lzy[x])return;
lzy[x<<]=lzy[x<<|]=lzy[x];
mx[x<<]=mx[x<<|]=lzy[x];
lzy[x]=;
}
void add(int x,int l,int r,int L,int R,int val)
{
if(l>=L&&r<=R){mx[x]=lzy[x]=val; return;}
pushdown(x);
int mid=((l+r)>>);
if(mid>=L)add(x<<,l,mid,L,R,val);
if(mid<R)add(x<<|,mid+,r,L,R,val);
pushup(x);
}
int ask(int x,int l,int r,int L,int R)
{
if(l>=L&&r<=R)return mx[x];
pushdown(x);
int ret=,mid=((l+r)>>);
if(mid>=L)ret=max(ret,ask(x<<,l,mid,L,R));
if(mid<R)ret=max(ret,ask(x<<|,mid+,r,L,R));
return ret;
}
void update(int x,int y,int val)
{
while(top[x]!=top[y])
{
if(dep[top[x]]<dep[top[y]])swap(x,y);
add(,,n,dfn[top[x]],dfn[x],val);
x=fa[top[x]];
}
if(dep[x]<dep[y])swap(x,y);
add(,,n,dfn[y],dfn[x],val);
}
bool query(int x,int y)
{
while(top[x]!=top[y])
{
if(dep[top[x]]<dep[top[y]])swap(x,y);
if(ask(,,n,dfn[top[x]],dfn[x])==tot) return ;
x=fa[top[x]];
}
if(dep[x]<dep[y])swap(x,y);
return (ask(,,n,dfn[y],dfn[x])==tot);
}
int main()
{
scanf("%d%d",&n,&q);
for(int i=,x,y;i<n;i++)
{
scanf("%d%d",&x,&y);
add(x,y); add(y,x);
}
dfs(,); top[]=; dfs2();
for(int i=,a,b,c,d;i<=q;i++)
{
scanf("%d%d%d%d",&a,&b,&c,&d);
update(a,b,++tot);
if(query(c,d))printf("Y\n");
else printf("N\n");
}
return ;
}
洛谷 P3398 仓鼠找sugar —— 树链剖分的更多相关文章
- 洛谷 3398 仓鼠找sugar——树链剖分
题目:https://www.luogu.org/problemnew/show/P3398 原来只要把值记录成第几次就行了. 别忘了while(top[a]!=top[b])之后还要走一步. #in ...
- 洛谷 P3398 仓鼠找sugar 解题报告
P3398 仓鼠找sugar 题目描述 小仓鼠的和他的基(mei)友(zi)sugar住在地下洞穴中,每个节点的编号为1~n.地下洞穴是一个树形结构.这一天小仓鼠打算从从他的卧室(a)到餐厅(b),而 ...
- 洛谷P3398 仓鼠找sugar [LCA]
题目传送门 仓鼠找sugar 题目描述 小仓鼠的和他的基(mei)友(zi)sugar住在地下洞穴中,每个节点的编号为1~n.地下洞穴是一个树形结构.这一天小仓鼠打算从从他的卧室(a)到餐厅(b),而 ...
- 洛谷P3398 仓鼠找sugar
题目描述 小仓鼠的和他的基(mei)友(zi)sugar住在地下洞穴中,每个节点的编号为1~n.地下洞穴是一个树形结构.这一天小仓鼠打算从从他的卧室(a)到餐厅(b),而他的基友同时要从他的卧室(c) ...
- 洛谷——P3398 仓鼠找sugar
https://www.luogu.org/problem/show?pid=3398#sub 题目描述 小仓鼠的和他的基(mei)友(zi)sugar住在地下洞穴中,每个节点的编号为1~n.地下洞穴 ...
- 洛谷 P3398 仓鼠找sugar 题解
每日一题 day44 打卡 Analysis 首先有一个结论:先找 p1=(a,b),p2=(c,d) 的LCA的深度,在与(a,c),(a,d),(b,c),(b,d)中最深的LCA n的深度比较, ...
- 洛谷 [P3398] 仓鼠找sugar
树剖求LCA 我们可以发现,两条路径ab,cd相交,当且仅当 dep[lca(a,b)]>=dep[lca(c,d)]&(lca(lca(a,b),c)==lca(a,b)||lca(l ...
- 洛谷P3412 仓鼠找$Sugar\ II$题解(期望+统计论?)
洛谷P3412 仓鼠找\(Sugar\ II\)题解(期望+统计论?) 标签:题解 阅读体验:https://zybuluo.com/Junlier/note/1327573 原题链接:洛谷P3412 ...
- 洛谷 P3384 【模板】树链剖分-树链剖分(点权)(路径节点更新、路径求和、子树节点更新、子树求和)模板-备注结合一下以前写的题目,懒得写很详细的注释
P3384 [模板]树链剖分 题目描述 如题,已知一棵包含N个结点的树(连通且无环),每个节点上包含一个数值,需要支持以下操作: 操作1: 格式: 1 x y z 表示将树从x到y结点最短路径上所有节 ...
随机推荐
- @ControllerAdvice全局异常拦截
@ControllerAdvice 拦截异常并统一处理 在spring 3.2中,新增了@ControllerAdvice 注解,可以用于定义@ExceptionHandler.@InitBinder ...
- vue组件---插槽
(1)插槽内容 Vue 实现了一套内容分发的 API,这套 API 的设计灵感源自 Web Components 规范草案,将 <slot> 元素作为承载分发内容的出口. 在父级组件里可以 ...
- 浅谈GFC
Web页面的布局,我们常见的主要有“浮动布局(float)”.“定位布局(position)”.“行内块布局(inline-block)”.“CSS3的多栏布局(Columns)”.“伸缩布局(Fle ...
- ThinkPHP---TP功能类之公文管理功能2----------继续完善
[前言] 之前已经完成了公文的添加和列表展示功能,今天继续完善.做下公文的编辑和删除功能. [主体] (1)分析 控制器:DocController.class.php 方法:edit(将模板展示和数 ...
- WebService接口数据传输加密
1.加密流程 客服端--->加密文本------>服务端接收到加密文本,通过固定加密密文进行解密,然后做相应处理------------>返回结果 2.固定密文创建 密文创建有很多种 ...
- 字符串--P1553 数字反转(升级版)
题目描述 给定一个数,请将该数各个位上数字反转得到一个新数. 这次与NOIp2011普及组第一题不同的是:这个数可以是小数,分数,百分数,整数.整数反转是将所有数位对调:小数反转是把整数部分的数反转, ...
- Python学习-变量
什么是变量? 概念:变量就是会变化的量,主要是“变”与“量”二字.变即是“变化”. 特点:与其他编程语言相同,变量是最基本的存储单位,是用来存放数据的容器.可以引用一个具体的数值,进而直接去改变这个引 ...
- java mysql prepareStatement模糊查询like使用注意
今天在使用mysql 的like语句是,发现prepareStatement的like语句和一般的=写法有一样. 当要使用prepareStatement的like查询时,按照一般写法,都会写成: S ...
- spring cloud feign 坑
feign是啥? 很多人可能对于feign 不是很熟悉,可以看一下其他网友的实例分享:spring cloud feign简介 如果觉得上面这个比较难的话,还有一个简单入门的:spring cplou ...
- 【Codeforces 675D】Tree Construction
[链接] 我是链接,点我呀:) [题意] 依次序将数字插入到排序二叉树当中 问你每个数字它的父亲节点上的数字是啥 [题解] 按次序处理每一个数字 对于数字x 找到最小的大于x的数字所在的位置i 显然, ...