题目: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 —— 树链剖分的更多相关文章

  1. 洛谷 3398 仓鼠找sugar——树链剖分

    题目:https://www.luogu.org/problemnew/show/P3398 原来只要把值记录成第几次就行了. 别忘了while(top[a]!=top[b])之后还要走一步. #in ...

  2. 洛谷 P3398 仓鼠找sugar 解题报告

    P3398 仓鼠找sugar 题目描述 小仓鼠的和他的基(mei)友(zi)sugar住在地下洞穴中,每个节点的编号为1~n.地下洞穴是一个树形结构.这一天小仓鼠打算从从他的卧室(a)到餐厅(b),而 ...

  3. 洛谷P3398 仓鼠找sugar [LCA]

    题目传送门 仓鼠找sugar 题目描述 小仓鼠的和他的基(mei)友(zi)sugar住在地下洞穴中,每个节点的编号为1~n.地下洞穴是一个树形结构.这一天小仓鼠打算从从他的卧室(a)到餐厅(b),而 ...

  4. 洛谷P3398 仓鼠找sugar

    题目描述 小仓鼠的和他的基(mei)友(zi)sugar住在地下洞穴中,每个节点的编号为1~n.地下洞穴是一个树形结构.这一天小仓鼠打算从从他的卧室(a)到餐厅(b),而他的基友同时要从他的卧室(c) ...

  5. 洛谷——P3398 仓鼠找sugar

    https://www.luogu.org/problem/show?pid=3398#sub 题目描述 小仓鼠的和他的基(mei)友(zi)sugar住在地下洞穴中,每个节点的编号为1~n.地下洞穴 ...

  6. 洛谷 P3398 仓鼠找sugar 题解

    每日一题 day44 打卡 Analysis 首先有一个结论:先找 p1=(a,b),p2=(c,d) 的LCA的深度,在与(a,c),(a,d),(b,c),(b,d)中最深的LCA n的深度比较, ...

  7. 洛谷 [P3398] 仓鼠找sugar

    树剖求LCA 我们可以发现,两条路径ab,cd相交,当且仅当 dep[lca(a,b)]>=dep[lca(c,d)]&(lca(lca(a,b),c)==lca(a,b)||lca(l ...

  8. 洛谷P3412 仓鼠找$Sugar\ II$题解(期望+统计论?)

    洛谷P3412 仓鼠找\(Sugar\ II\)题解(期望+统计论?) 标签:题解 阅读体验:https://zybuluo.com/Junlier/note/1327573 原题链接:洛谷P3412 ...

  9. 洛谷 P3384 【模板】树链剖分-树链剖分(点权)(路径节点更新、路径求和、子树节点更新、子树求和)模板-备注结合一下以前写的题目,懒得写很详细的注释

    P3384 [模板]树链剖分 题目描述 如题,已知一棵包含N个结点的树(连通且无环),每个节点上包含一个数值,需要支持以下操作: 操作1: 格式: 1 x y z 表示将树从x到y结点最短路径上所有节 ...

随机推荐

  1. 00HyperText Markup Language

    HyperText Markup Language HTML超文本标记语言是一种用于创建网页的标准标记语言用于显示网页内容,HTML运行在浏览器上,由浏览器来解析,您可以使用 HTML 来建立自己的 ...

  2. 二叉查找树(Binary Search Tree)

    Date:2019-06-25 14:40:32 基本操作 注意:数据量较大时,插入建树的时间复杂度会很高,慎用! //查找 void Search(node *root, int x) { if(r ...

  3. 面向对象程序设计--Java语言第一周编程题:分数

    分数 题目内容: 设计一个表示分数的类Fraction.这个类用两个int类型的变量分别表示分子和分母. 这个类的构造函数是: Fraction(int a, int b) 构造一个a/b的分数. 这 ...

  4. [HNOI]2003 消防局的建立

    消防局的建立 本题地址:http://www.luogu.org/problem/show?pid=2279 题目描述 2020年,人类在火星上建立了一个庞大的基地群,总共有n个基地.起初为了节约材料 ...

  5. pygame 方块随机飞舞动画

    import pygame import random # default WIDTH=1280 HEIGHT=1060 FPS=60 sum=0 # set color WHITE=(255,255 ...

  6. <MySQL>入门五 视图

    -- 视图 /* 含义:虚拟表,和普通的表一样使用 mysql5.1版本的新特性,是通过表动态生成的数据,只保存了sql的逻辑,不保存查询的结果 应用场景: - 多个地方用到同样的查询结果 - 该查询 ...

  7. 银河英雄传说 2002年NOI全国竞赛

    时间限制: 1 s 空间限制: 256000 KB 题目等级 : 大师 Master 题目描述 Description 公元五八○一年,地球居民迁移至金牛座α第二行星,在那里发表银河联邦创立宣言,同年 ...

  8. 使用java操作hbase(单节点)

    1.在运行java代码之前,一定要先启动Hbase,很重要!!    cd /home/cx/itcast/hbase-1.2.6/bin   ./start-hbase.sh 2.新建一个java项 ...

  9. project处理 InteropServices.COMException 异常

    project文件无法上传,在上传中的hangfire出现了这个异常 System.Runtime.InteropServices.COMException 这个是因为website的权限是IUser ...

  10. JAVA和C语言的区别

    java语言和c语言的区别:                                      1 un 公司推出的Java 是面向对象程序设计语言,其适用于Internet 应用的开发,称为 ...