洛谷 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结点最短路径上所有节 ...
随机推荐
- 观察者模式在Foundation框架通知中的应用
GitHub传送门 1.何为观察者模式? 观察者设计模式定义了对象间的一种一对多的依赖关系,以便一个对象的状态发生变化时,所有依赖于它的对象都得到通知并自动刷新. 举个简单的例子:你和你的舍友都订阅了 ...
- 如何允许WebGL从本地载入资源
随着mono-design不断推广,用户越来越多,陆续有电话来询问“为什么3D展现的时候,是一团黑?”,针对这个问题,专门写个帖子说明原因并给出解决方案,并且在mono-design编辑器中加了判断功 ...
- Qt 如何处理密集型耗时的事情
有时候需要处理一些跟界面无关的但非常耗时的事情,这些事情跟界面在同一个线程中,由于时间太长,导致界面无法响应,处于“假死”状态.例如:在应用程序中保存文件到硬盘上,从开始保存直到文件保存完毕,程序不响 ...
- Luogu P4016 「 网络流 24 题 」负载平衡问题
吐槽题目难度,这个题建模好像比前两个都要难,但是难度评级却比第二个要低. 解题思路 依旧是考虑如何建模和建立源点汇点.每个点的货物数量到最后都一样的话肯定是等于他们的平均值.用 $num$ 数组存储原 ...
- Centos7安装MySQL5.7(yum)
本人尝试过使用源码安装方式,那叫一个头疼,各种问题,于是采用yum方式安装,没想到如此简单: 此服务器是刚买的,所以以前没有安装过mysql,如果以前安装过mysql的,好像要卸载干净再安装(其实我也 ...
- Python关于导入模块的一些感想:
写项目的时候,碰到这种情况 程序业务为core,里面有两个目录,core1 和core2 core1中有三个模块,business main main1 程序入口为bin目录下的project ...
- 转来的--轻松自动化---selenium-webdriver(python) (七)---定位iframe——转来的
本节知识点: 多层框架或窗口的定位: switch_to_frame() switch_to_window() 智能等待: implicitly_wait() 对于一个现代的web应用,经常会出现框架 ...
- 匹配 C 语言样式字符串
#include <stdio.h> char haha[] = "nihaoma" "niubi" "\"hello worl ...
- L2-011. 玩转二叉树(不建树)
L2-011. 玩转二叉树 给定一棵二叉树的中序遍历和前序遍历,请你先将树做个镜面反转,再输出反转后的层序遍历的序列.所谓镜面反转,是指将所有非叶结点的左右孩子对换.这里假设键值都是互不相等的正整 ...
- Hashing - Hard Version
Hashing - Hard Version Given a hash table of size N, we can define a hash function . Suppose that th ...