传送门

首先很显然,从人形起点出发能到的点和狼形能到终点的点都是一个联通块,如果能从起点到终点则说明这两个联通块有交

这个时候可以请出我们的克鲁斯卡尔重构树,即对原图分别建两棵重构树,一棵边权为两端点较小值,边权从大到小排序后构建,另一棵反过来,所以构完后第一棵重构树某个点权值要小于等于子树内的点,第二棵某点权值大于等于子树内点

对于一个询问,起点在第一棵树向上倍增找深度最浅,权值\(\ge l\)的祖先x,终点在第二棵树向上倍增找深度最浅,权值\(\le l\)的祖先y,那么x和y就是上面说到的联通块.现在问题转化为子树判交,把询问离线,把y挂在x上,在第一棵树内从叶子开始向上做,做到某个点就x查询对应y子树对应的dfn区间在线段树上有没有x子树的叶子节点

代码极丑qwq

// luogu-judger-enable-o2
#include<bits/stdc++.h>
#define LL long long
#define db double
#define il inline
#define re registerusing namespace std;
const int N=2e5+10;
const db eps=1e-5;
il LL rd()
{LL x=0,w=1;char ch=0;while(ch<'0'||ch>'9') {if(ch=='-') w=-1;ch=getchar();}while(ch>='0'&&ch<='9') {x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}return x*w;
}
int ed[N<<2];
struct edge
{int x,y,w;
}ee[N<<1];
int ff[N<<1];
il int findf(int x){return ff[x]==x?x:ff[x]=findf(ff[x]);}
struct trr
{int a[N<<1],fa[N<<1][20],ch[N<<1][2],sz[N<<1],dfn[N<<1],tt,s[N<<1],tp;trr(){tp=0;}il void init(int n){tt=n;}il void ad(int x,int y,int w){a[++tt]=w,ff[x]=ff[y]=fa[x][0]=fa[y][0]=tt,ch[tt][0]=x,ch[tt][1]=y;}void pree(int x){if(!x) return;s[++tp]=x,dfn[x]=tp,sz[x]=1;for(int j=1;j<20;++j){fa[x][j]=fa[fa[x][j-1]][j-1];if(!fa[x][j]) break;}pree(ch[x][0]),pree(ch[x][1]);sz[x]+=sz[ch[x][0]]+sz[ch[x][1]];}il int findd(int x,int p,bool op){if(op) {for(int j=19;~j;--j) if(a[fa[x][j]]>=p) x=fa[x][j];}else {for(int j=19;~j;--j) if(fa[x][j]&&a[fa[x][j]]<=p) x=fa[x][j];}return x;}
}tr[2];
il bool cmp1(edge a,edge b){return a.w>b.w;}
il bool cmp2(edge a,edge b){return a.w<b.w;}
int qto[N<<1],qnt[N<<1],qhd[N<<1],qt;
il void qwq(int x,int y){++qt,qto[qt]=y,qnt[qt]=qhd[x],qhd[x]=qt;}
int n,m,q;
bool an[N];
struct sgmt
{bool s[(N<<1)*30];int ch[(N<<1)*30][2],rt[N<<1],tt;sgmt(){tt=0;}il void inst(int o,int x){int l=1,r=n+n-1;s[o]=1;while(l<r){int mid=(l+r)>>1;if(x<=mid) o=ch[o][0]=++tt,r=mid;else o=ch[o][1]=++tt,l=mid+1;s[o]=1;}}int merge(int o1,int o2){if(!o1||!o2) return o1+o2;if(o1==o2) return o1;int o=++tt;s[o]=s[o1]|s[o2];ch[o][0]=merge(ch[o1][0],ch[o2][0]);ch[o][1]=merge(ch[o1][1],ch[o2][1]);return o;}bool quer(int o,int l,int r,int ll,int rr){if(!o) return 0;if(ll<=l&&r<=rr) return s[o];bool an=0;int mid=(l+r)>>1;if(ll<=mid) an|=quer(ch[o][0],l,mid,ll,rr);if(rr>mid) an|=quer(ch[o][1],mid+1,r,ll,rr);return an;}
}sht;int main()
{n=rd(),m=rd(),q=rd();tr[0].init(n),tr[1].init(n);for(int i=1;i<=n;++i) tr[0].a[i]=tr[1].a[i]=i;for(int i=1;i<=m;++i) ed[i<<1]=rd()+1,ed[i<<1|1]=rd()+1;for(int i=1;i<=m;++i) ee[i]=(edge){ed[i<<1],ed[i<<1|1],min(ed[i<<1],ed[i<<1|1])};sort(ee+1,ee+m+1,cmp1);for(int i=1;i<n+n;++i) ff[i]=i;for(int i=1;i<=m;++i) if(findf(ee[i].x)^findf(ee[i].y)) tr[0].ad(ff[ee[i].x],ff[ee[i].y],ee[i].w);tr[0].pree(n+n-1);for(int i=1;i<=m;++i) ee[i]=(edge){ed[i<<1],ed[i<<1|1],max(ed[i<<1],ed[i<<1|1])};sort(ee+1,ee+m+1,cmp2);for(int i=1;i<n+n;++i) ff[i]=i;for(int i=1;i<=m;++i) if(findf(ee[i].x)^findf(ee[i].y)) tr[1].ad(ff[ee[i].x],ff[ee[i].y],ee[i].w);tr[1].pree(n+n-1);for(int i=1;i<=q;++i){int x=rd()+1,y=rd()+1,l=rd()+1,r=rd()+1;x=tr[0].findd(x,l,1),y=tr[1].findd(y,r,0);qwq(x,y);}for(int i=n+n-1;i;--i){int x=tr[0].s[i];if(x<=n) sht.inst(sht.rt[x]=++sht.tt,tr[1].dfn[x]);else sht.rt[x]=sht.merge(sht.rt[tr[0].ch[x][0]],sht.rt[tr[0].ch[x][1]]);for(int j=qhd[x];j;j=qnt[j]){int xx=qto[j];an[j]=sht.quer(sht.rt[x],1,n+n-1,tr[1].dfn[xx],tr[1].dfn[xx]+tr[1].sz[xx]-1);}}for(int i=1;i<=q;++i) printf("%d\n",an[i]);return 0;
}

转载于:https://www.cnblogs.com/smyjr/p/10186880.html

luogu P4899 [IOI2018] werewolf 狼火相关推荐

  1. P4899 [IOI2018] werewolf 狼人(kruskal 重构树 + 主席树)

    P4899 [IOI2018] werewolf 狼人 给定一个有nnn个点mmm条边的无向图,有QQQ个询问 每次输入S,E,L,RS, E, L, RS,E,L,R,表示你在SSS点出发,要到EE ...

  2. LG P4899 [IOI2018] werewolf 狼人(kruskal重构树,二维数点)

    LG P4899 [IOI2018] werewolf 狼人 Solution 我们发现010101限制长这样子: ∃x(minids−>x≥L&maxidx−>e≤R)→1\ex ...

  3. 【luogu P4899】werewolf 狼人(最小生成树)(主席树)

    werewolf 狼人 题目链接:luogu P4899 题目大意 给你一个无向图,然后每次要从一个地方走到另外一个地方. 然后你在走的过程中要在一个点转换形态,转换之前你只能走大于等于 L 的点,转 ...

  4. p4899 [IOI2018] werewolf 狼人

    分析 我用的主席树维护qwq 代码 #include<iostream> #include<cstdio> #include<cstring> #include&l ...

  5. [IOI2018] werewolf 狼人 题解

    [IOI2018] werewolf 狼人 [IOI2018] werewolf 狼人 可以考虑到每一条边能否通过对于人形态来说,取决于两点的最小值,对于狼形态来说取决两点的最大值. 那么我们不妨考虑 ...

  6. [IOI2018] werewolf 狼人

    [IOI2018] werewolf 狼人 IOI2018题解 (其实原题强制在线,要用主席树) 代码: 注意: 1.下标从0~n-1 2.kruskal重构树开始有n个节点,tot从n开始,++to ...

  7. 本周AI热点回顾:「时空版」Transformer训练速度远超3D CNN;拒绝内卷的AI狼火了!不想抓羊只想躺!...

    ‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍点击左上方蓝字关注我们 01 「时空版」Transformer训练速度远超3D CNN,提速3倍! Facebook AI推出了全新的视频理解架构TimeSform ...

  8. 这个拒绝内卷的狼火了!高智商却自暴自弃,不想抓羊只想躺

    点击"开发者技术前线",选择"星标????" 让一部分开发者看到未来 新智元报道 来源:B站 近日,一个狼吃羊的AI火了!在一个狼吃羊的AI智障游戏中,狼发现自 ...

  9. 这个拒绝内卷的AI狼火了!高智商却自暴自弃,不想抓羊只想躺

      新智元报道   来源:B站等 编辑:Yaxin [新智元导读]近日,一个狼吃羊的AI火了!在一个狼吃羊的AI智障游戏中,狼发现自己吃不到羊,直接选择了「自杀」.然而,狼选择撞石的原因竟是「自杀分数 ...

最新文章

  1. 软件篇:程序员如何提升自己的技能
  2. IPMI与iDrac的区别
  3. stm32f10x_it.c 定义的程序列表模板(stm32f103x_it.c中放的是中断的空函数)
  4. html按钮不可选中,如何使HTML文本不可选择
  5. jieba分词提取小说人名
  6. 轮询锁使用时遇到的问题与解决方案!
  7. 5场直播丨PostgreSQL、openGauss、Oracle、GoldenDB、EsgynDB
  8. suse linux vnc配置文件,怎么在linux suse中配置VNC服务器
  9. 1_Small Data Challenges in Big Data Era
  10. mysql 的基本用法_mysql的基本用法
  11. STM32f407 DCMI方式驱动 OV2640
  12. 视频教程-隐马尔科夫算法:中文分词神器-深度学习
  13. 转载:汇总详解:矩阵的迹以及迹对矩阵求导
  14. Nvidia Agx Xavier平台无PD控制器USB接口调试
  15. 淘宝店群玩法,双十一商家自运营,淘宝店群好处,建淘宝店群门槛条件
  16. python3.x程序设计基础周元哲答案_周元哲
  17. unsigned char型整数
  18. php usc2,CSDN 免积分下载原理
  19. 美国 转专业 计算机,​转专业申请计算机硕士,美国这些学校供你选择
  20. 交错校验法 / interleaving

热门文章

  1. php导航遍历代码,目录遍历函数_php
  2. 仓储搬运机器人_浅谈仓储搬运机器人那点事儿
  3. Excel中如何按照最右边的分隔符从右向左取字符串
  4. 证书全部无效的解决方法
  5. 抖音直播间没人气怎么办?抖音直播间人气怎么升上去?
  6. 榆林国号和计算机学校,榆林学院排名2021 陕西排名第26全国排名第607
  7. 有哪些值得推荐的半入耳式耳机?高音质半入耳式耳机
  8. 纯属搞笑,要是真的就太。。。
  9. 昨晚停网后,写了一段代码破解隔壁小姐姐的wifi密码...
  10. 四步编写第一个java程序