http://uoj.ac/problem/407

分析:

  • 分别建立最小/最大kruskal重构树。
  • 每次询问给出的两个点能走到的部分分别对应两棵树\(dfs\)序的一段区间。
  • 转化成判断矩形中是否有点。

代码:

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <cmath>
#include "werewolf.h"
using namespace std;
#define M 400050
#define vi vector<int>
int n,m,q_times,fa[M],ln;
int dfn[2][M],enp[2][M],Ls[2][M],Rs[2][M],dfc,w[2][M];
int f[2][20][M],idf[2][M],root[M],ls[M*22],rs[M*22],siz[M*22],cnt;
char buf[100000],*p1,*p2;
#define nc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++)
int rd() {
int x=0; char s=nc();
while(s<'0') s=nc();
while(s>='0') x=(((x<<2)+x)<<1)+s-'0',s=nc();
return x;
}
struct A {
int a,b,c;
bool operator < (const A &u) const {
return c>u.c;
}
}e[M];
int find(int x) {return fa[x]==x?x:fa[x]=find(fa[x]);}
void df1(int x,int o) {
dfn[o][x]=++dfc;
idf[o][dfc]=x;
if(Ls[o][x]) df1(Ls[o][x],o);
if(Rs[o][x]) df1(Rs[o][x],o);
enp[o][x]=dfc;
}
void update(int l,int r,int x,int &p,int q) {
p=++cnt; siz[p]=siz[q]+1; ls[p]=ls[q]; rs[p]=rs[q];
if(l==r) return ;
int mid=(l+r)>>1;
if(x<=mid) update(l,mid,x,ls[p],ls[q]);
else update(mid+1,r,x,rs[p],rs[q]);
}
int query(int l,int r,int x,int y,int p,int q) {
if(x<=l&&y>=r) return siz[p]-siz[q];
int mid=(l+r)>>1,re=0;
if(x<=mid) re+=query(l,mid,x,y,ls[p],ls[q]);
if(y>mid) re+=query(mid+1,r,x,y,rs[p],rs[q]);
return re;
}
vi check_validity(int n,vi EX,vi EY,vi QX,vi QY,vi QL,vi QR) {
ln=n*2-1;
m=EX.size();
int i,tot=n;
for(i=1;i<=m;i++) {
e[i].a=EX[i-1]; e[i].b=EY[i-1];
e[i].a++; e[i].b++;
e[i].c=min(e[i].a,e[i].b);
}
sort(e+1,e+m+1);
for(i=1;i<=ln;i++) fa[i]=i;
for(i=1;i<=m;i++) {
int dx=find(e[i].a),dy=find(e[i].b);
if(dx!=dy) {
fa[dx]=fa[dy]=++tot; Ls[0][tot]=dx; Rs[0][tot]=dy; w[0][tot]=e[i].c; f[0][0][dx]=f[0][0][dy]=tot;
}
}
df1(tot,0); dfc=0;
for(i=1;i<=ln;i++) fa[i]=i;
tot=n;
for(i=1;i<=m;i++) e[i].c=max(e[i].a,e[i].b);
sort(e+1,e+m+1);
for(i=m;i;i--) {
int dx=find(e[i].a),dy=find(e[i].b);
if(dx!=dy) {
fa[dx]=fa[dy]=++tot; Ls[1][tot]=dx; Rs[1][tot]=dy; w[1][tot]=e[i].c; f[1][0][dx]=f[1][0][dy]=tot;
}
}
df1(tot,1);
int j,k;
for(i=0;i<2;i++) {
for(j=1;(1<<j)<=ln;j++) {
for(k=1;k<=ln;k++) {
f[i][j][k]=f[i][j-1][f[i][j-1][k]];
}
}
}
for(i=1;i<=dfc;i++) {
root[i]=root[i-1];
int x=idf[1][i];
if(x<=n) {
update(1,dfc,dfn[0][x],root[i],root[i]);
}
}
vi ans;
int x,y,l,r;
q_times=QX.size();
for(j=0;j<q_times;j++) {
x=QX[j]; y=QY[j]; l=QL[j]; r=QR[j];
x++;y++;l++;r++;
for(i=19;i>=0;i--) {
if(f[0][i][x]&&w[0][f[0][i][x]]>=l) x=f[0][i][x];
if(f[1][i][y]&&w[1][f[1][i][y]]<=r) y=f[1][i][y];
}
int t=query(1,dfc,dfn[0][x],enp[0][x],root[enp[1][y]],root[dfn[1][y]-1]);
ans.push_back(t>0);
}
return ans;
}

UOJ_407_【IOI2018】狼人的更多相关文章

  1. [IOI2018]狼人

    [IOI2018]狼人 luogu UOJ 对人形和狼形分别建克鲁斯卡尔重构树 每次询问就是对于两棵树dfs序的一个二维数点,主席树维护 #include<bits/stdc++.h> u ...

  2. LOJ.2865.[IOI2018]狼人(Kruskal重构树 主席树)

    LOJ 洛谷 这题不就是Peaks(加强版)或者归程么..这算是\(IOI2018\)撞上\(NOI2018\)的题了? \(Kruskal\)重构树(具体是所有点按从小到大/从大到小的顺序,依次加入 ...

  3. [IOI2018]狼人——kruskal重构树+可持久化线段树

    题目链接: IOI2018werewolf 题目大意:给出一张$n$个点$m$条边的无向图,点和边可重复经过,一个狼人初始为人形,有$q$次询问,每次询问要求人形态只能处于编号不小于$L$的点,狼形态 ...

  4. Luogu4899 IOI2018狼人(kruskal重构树+主席树)

    可以发现询问的即是“由起点开始‘只经过编号大于等于l的点’所形成的连通块”与“由终点开始‘只经过编号小于等于r的点’所形成的连通块”是否有交集.于是建出重构树,就可以知道每个询问的连通情况了.现在要知 ...

  5. ghj1222被坑记录[不持续更新]

    考试注意事项:link1 link2 (密码:wangle) 调不出来bug,可以先透彻一会儿或者是上个厕所或者坐一会别的题(间隔至少20min),然后通读代码 -1. 考试先读题,读题之后搞出一个做 ...

  6. [note]克鲁斯卡尔重构树

    克鲁斯卡尔重构树 又叫并查集重构树 大概在NOI2018之前还是黑科技 现在?烂大街了 主要是针对图上的对边有限制的一类问题 比如每次询问一个点u不能经过边权大于w的边能走到的第k大点权是多少 也就是 ...

  7. NOIWC2019游记

    更新完了? ghj1222这个智障因为NOIP考的太菜没有去THUWC和PKUWC,但是NOIWC还是苟进去了 由于已经结束了,好多事实忘了,所以可能不完整 2019/1/23 Wednesday 明 ...

  8. [IOI2018] werewolf 狼人

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

  9. [IOI2018] werewolf 狼人 kruskal重构树,主席树

    [IOI2018] werewolf 狼人 LG传送门 kruskal重构树好题. 日常安利博客文章 这题需要搞两棵重构树出来,这两棵重构树和我们平时见过的重构树有点不同(据说叫做点权重构树?),根据 ...

随机推荐

  1. 37:密码截取(回文串manacher算法)

    题目描述:Catcher是MCA国的情报员,他工作时发现敌国会用一些对称的密码进行通信,比如像这些ABBA,ABA,A,123321,但是他们有时会在开始或结束时加入一些无关的字符以防止别国破解.比如 ...

  2. A、B两伙马贼意外地在一片沙漠中发现了一处金矿,双方都想独占金矿,但各自的实力都不足以吞下对方,经过谈判后,双方同意用一个公平的方式来处理这片金矿。处理的规则如下:他们把整个金矿分成n段,由A、B开始轮流从最左端或最右端占据一段,直到分完为止。 马贼A想提前知道他们能分到多少金子,因此请你帮忙计算他们最后各自拥有多少金子?(两伙马贼均会采取对己方有利的策略)

    第一种做法:这种方法,算法复杂性大,重复的递归 #include "stdafx.h" #include<iostream> #include<vector> ...

  3. 规范-Git打标签与版本控制

    Git打标签与版本控制规范 前言 本文适用于使用Git做VCS(版本控制系统)的场景. 用过Git的程序猿,都喜欢其分布式架构带来的commit快感.不用像使用SVN这种集中式版本管理系统,每一次提交 ...

  4. hadoop 出现FATAL conf.Configuration: error parsing conf file,异常

    FATAL conf.Configuration: error parsing conf file: com.sun.org.apache.xerces.internal.impl.io.Malfor ...

  5. Devexpress Spreadsheet 中文教程

    http://blog.csdn.net/hotmee/article/details/50554381

  6. Swift 学习笔记 (类和结构体)

    类和结构体是一种多功能且灵活的构造体.通过使用与现存常量 变量 函数完全相同的语法来在类和结构体中定义属性和方法以添加功能. Swift中不需要你为自定义的类和结构体创建独立的结构和实现文件.在Swi ...

  7. 关于Wix的源代码

    Wix的源代码有两种方式可以获得,以3.8为例: 在Release的页面下载wix38-debug.zip 通过SourceCode页面下载,http://wix.codeplex.com/Sourc ...

  8. freetype下载和配置

    一 下载编译freetype库 1 下载 地址:http://www.freetype.org/ 得到压缩文件:freetype-2.5.3.tar.gz 2 解压: 直接解压,得到文件夹freety ...

  9. lambda map filter 用法

    lambda 可以这样认为,lambda作为一个表达式 非常容易理解,在这里lambda简化了函数定义的书写形式.是代码更为简洁,但是使用函数的定义方式更为直观,易理解. #定义函数:普通方式 def ...

  10. Hadoop-2.2.0中文文档—— MapReduce 下一代--容量调度器

    目的 这份文档描写叙述 CapacityScheduler,一个为Hadoop能同意多用户安全地共享一个大集群的插件式调度器,如他们的应用能适时被分配限制的容量. 概述 CapacitySchedul ...