点此看题面

大致题意: 给你一张\(DAG\),多组询问,每次问你在起点不为某些点的前提下,到达给定终点的最大距离是多少。

设阈值

由于限制点数总和与\(n\)同阶,因此容易想到去设阈值。

对于限制点数少于\(\sqrt n\)的询问,首先我们可以\(O(n\sqrt n)\)预处理出对于每个点到其距离前\(\sqrt n\)大的点及其距离。

关于这个,可以通过在\(DAG\)上归并转移处理出来。

然后询问时只要\(O(\sqrt n)\)对于给定终点找到第一个非限制点即可。

对于限制点数大于等于\(\sqrt n\)的询问,我们直接\(O(n)\)暴力。

由于这种询问个数不超过\(\sqrt n\)个,因此时间复杂度也是\(O(n\sqrt n)\)的。

代码

#include<bits/stdc++.h>
#define Tp template<typename Ty>
#define Ts template<typename Ty,typename... Ar>
#define Reg register
#define RI Reg int
#define Con const
#define CI Con int&
#define I inline
#define W while
#define N 100000
#define M 200000
#define SN 400
#define Gmax(x,y) (x<(y)&&(x=(y)))
#define add(x,y) (e[++ee].nxt=lnk[x],e[lnk[x]=ee].to=y)
#define add_(x,y) (e_[++ee_].nxt=lnk_[x],e_[lnk_[x]=ee_].to=y)
using namespace std;
int n,m,sn,fg,ee,ee_,s[N+5],lnk[N+5],lnk_[N+5];struct edge {int to,nxt;}e[M+5],e_[M+5];
class FastIO
{
private:
#define FS 100000
#define tc() (A==B&&(B=(A=FI)+fread(FI,1,FS,stdin),A==B)?EOF:*A++)
#define pc(c) (C==E&&(clear(),0),*C++=c)
#define tn (x<<3)+(x<<1)
#define D isdigit(c=tc())
int T;char c,*A,*B,*C,*E,FI[FS],FO[FS],S[FS];
public:
I FastIO() {A=B=FI,C=FO,E=FO+FS;}
Tp I void read(Ty& x) {x=0;W(!D);W(x=tn+(c&15),D);}
Ts I void read(Ty& x,Ar&... y) {read(x),read(y...);}
Tp I void write(Ty x) {W(S[++T]=x%10+48,x/=10);W(T) pc(S[T--]);}
Tp I void writeln(Con Ty& x) {write(x),pc('\n');}
I void writeNA() {pc('-'),pc('1'),pc('\n');}
I void clear() {fwrite(FO,1,C-FO,stdout),C=FO;}
#undef D
}F;
class ListDper//预处理
{
private:
int f[N+5][SN+5],g[N+5][SN+5],f_[SN+5],g_[SN+5],used[N+5];
public:
I void Init()//预处理
{
RI i,j,w,k,px,py,pt,ti=0;for(i=1;i<=n;++i) f[i][1]=0,g[i][1]=i;//初始化
for(i=1;i<=n;++i) for(j=lnk[i];j;j=e[j].nxt)//枚举点转移
{
#define Push1 (f_[pt]=f[i][px]+1,used[g_[pt++]=g[i][px++]]=ti)
#define Push2 (f_[pt]=f[k][py],used[g_[pt++]=g[k][py++]]=ti)
++ti,k=e[j].to,px=py=pt=1;W(g[i][px]&&g[k][py]&&pt<=sn)//归并
{
if(used[g[i][px]]==ti) {++px;continue;}//每个点只考虑一次,这里用了时间戳
if(used[g[k][py]]==ti) {++py;continue;}//同上
f[i][px]+1>=f[k][py]?Push1:Push2;//注意转移时距离会加1
}
W(g[i][px]&&pt<=sn) used[g[i][px]]^ti?Push1:++px;//处理剩余点
W(g[k][py]&&pt<=sn) used[g[k][py]]^ti?Push2:++py;//同上
for(w=1;w^pt;++w) f[k][w]=f_[w],g[k][w]=g_[w];//更新数组
}
}
I void Solve(CI x)//求答案
{
RI p=1;W(g[x][p]&&s[g[x][p]]==fg) ++p;//扫一遍求答案
g[x][p]?F.writeln(f[x][p]):F.writeNA();//输出答案
}
}D;
class BruteForceSolver//暴力
{
private:
int dis[N+5];
public:
I void Solve(CI x)
{
RI i,j,ans=-1;for(i=1;i^x;++i) dis[i]=-1e9;dis[x]=0;//初始化赋值
for(i=x;i;--i) for(s[i]^fg&&Gmax(ans,dis[i]),j=lnk_[i];j;j=e_[j].nxt) Gmax(dis[e_[j].to],dis[i]+1);//暴力
~ans?F.writeln(ans):F.writeNA();//输出答案
}
}B;
int main()
{
RI Qtot,i,x,y,z;for(F.read(n,m,Qtot),sn=sqrt(n),i=1;i<=m;++i) F.read(x,y),add(x,y),add_(y,x);//读入+建边
D.Init();W(Qtot--) {for(F.read(x,y),++fg,i=1;i<=y;++i) F.read(z),s[z]=fg;y<sn?D.Solve(x):B.Solve(x);}//处理询问
return F.clear(),0;
}

【LOJ2838】「JOISC 2018 Day 3」比太郎的聚会(设阈值预处理/分块)的更多相关文章

  1. 「JOISC 2018 Day 3」比太郎的聚会

    题解: 很套路的题目 我们按照询问中的不算的个数是否大于$block$分类 如果大于,就$O(n)dp$一下 如果小于,就预处理出到每个点前$block$小的点 $block取\sqrt{n}$的话复 ...

  2. loj#2838 「JOISC 2018 Day 3」比太郎的聚会

    分析 预处理每个点的前根号小的距离 对于每次询问删除点小于根号则已经处理好 否则直接暴力dp即可 代码 #include<bits/stdc++.h> using namespace st ...

  3. [LOJ #2833]「JOISC 2018 Day 1」帐篷

    题目大意:有一个$n\times m$的网格图,若一个人的同一行或同一列有人,他就必须面向那个人,若都无人,就可以任意一个方向.若一个人无法确定方向,则方案不合法,问不同的方案数.$n,m\leqsl ...

  4. LOJ 2840「JOISC 2018 Day 4」糖

    有趣的脑子题(可惜我没有脑子 好像也可以称为模拟费用流(? 我们考虑用链表维护这个东西 再把贡献扔到堆里贪心就好了 大概就是类似于有反悔机制的贪心?我们相当于把选中的一个打上一个-v的tag然后如果选 ...

  5. LOJ #2831. 「JOISC 2018 Day 1」道路建设 线段树+Link-cut-tree

    用 LCT 维护颜色相同连通块,然后在线段树上查一下逆序对个数就可以了. code: #include <cstdio> #include <algorithm> #inclu ...

  6. Loj #2731 「JOISC 2016 Day 1」棋盘游戏

    Loj 2731 「JOISC 2016 Day 1」棋盘游戏 JOI 君有一个棋盘,棋盘上有 \(N\) 行 \(3\) 列 的格子.JOI 君有若干棋子,并想用它们来玩一个游戏.初始状态棋盘上至少 ...

  7. 【LibreOJ】#6354. 「CodePlus 2018 4 月赛」最短路 异或优化建图+Dijkstra

    [题目]#6354. 「CodePlus 2018 4 月赛」最短路 [题意]给定n个点,m条带权有向边,任意两个点i和j还可以花费(i xor j)*C到达(C是给定的常数),求A到B的最短距离.\ ...

  8. 「JOISC 2016 Day 1」棋盘游戏

    「JOISC 2016 Day 1」棋盘游戏 先判无解:第1,3行有连续的空格或四个角有空格. 然后可以发现有解的情况第1,3行可以在任意时间摆放. 对于某一列,若第2行放有棋子,那么显然可以把棋盘分 ...

  9. 「JOISC 2015 Day 1」卡片占卜

    题目描述 K 理事长是占卜好手,他精通各种形式的占卜.今天,他要用正面写着 I ,背面写着 O 的卡片占卜一下日本 IOI 国家队的选手选择情况. 占卜的方法如下: 首先,选取五个正整数 A,B,C, ...

随机推荐

  1. WPF 字体设置

    原文:WPF 字体设置 WPF 主界面 更换字体 可全局 但是有的时候有的窗体 字体还是没变 可以做全局样式 <Window x:Class="CLeopardTestWpf.Main ...

  2. 用OC基于数组实现循环队列

    一.简言 使用数组实现循环队列时,始终会有一个空余的位置预留着,作为一个判决队列已满的条件(当然也可以采用其他方式).在前面已经用C++介绍了基本的算法,可以去回顾一下https://www.cnbl ...

  3. Qt Designer布局预览正常,代码调用时所有控件堆在一起

    一.实验环境 1.Windows10x64 2.anaconda4.6.9 + python3.7.1(anaconda集成,不需单独安装) 3.pyinstaller3.5 二.问题描述 1.Qt ...

  4. 搭建Tomcat服务器访问本地资源

    目标,搭建Tomcat服务器,使同网络段下其他电脑可以访问分享的文件 下载安装Tomcat 如下图,在官网http://Tomcat.apache.org/下载对应版本的Tomcat,解压安装即可 启 ...

  5. 几个高逼格 Linux 命令!

    作者:忧郁巫师 https://dwz.cn/A1FOjLXk 1. sl 命令 你会看到一辆火车从屏幕右边开往左边…… 安装 $ sudo apt-get install sl 运行 $ sl 命令 ...

  6. angular 前端路由不生效解决方案

    angular 前端路由不生效解决方案 Intro 最近使用 Angular 为我的活动室预约项目开发一个前后端分离的客户端,在部署上遇到了一个问题,前端路由不生效,这里记录一下.本地开发正常,但是部 ...

  7. Revit二次开发 屏蔽复制构件产生的重复类型提示窗

    做了很久码农,也没个写博客的习惯,这次开始第一次写博客. 这个问题也是折腾了我接近一天时间,网上也没有任何的相关博文,于是决定分享一下,以供同样拥有此问题的小伙伴们参考. 内容源于目前在做的一个项目, ...

  8. Javase之多线程(2)

    多线程(2) 线程的生命周期 新建:创建线程对象 就绪:有执行资格,没有执行权 运行:有资格运行,有执行权 ​ 阻塞:由一些操作让线程处于改状态.没有执行资格,没有执行权,而通过另一些操作激活它,激活 ...

  9. qt构建错误: dependent "*.h" does not exist.

    项目中需要维护一套qt工程,今天发现一个头文件名称中单词拼写错误,就改正了,结果重新构建提示: dependent "*.h" does not exist. 原因:修改了文件后, ...

  10. 在linux上安装postgresql数据库

    #postgres useradd postgres chown -R postgres:postgres /media su postgres mkdir -p /media/Data1/postg ...