洛谷 P5332 - [JSOI2019]精准预测(2-SAT+bitset+分块处理)
七月份(7.31)做的题了,题解到现在才补,不愧是 tzc
首先不难发现题目中涉及的变量都是布尔型变量,因此可以考虑 2-SAT,具体来说,我们将每个人在每个时刻的可能的状态表示出来。我们开两个二维变量 \(\text{Live}(i,t)\) 表示第 \(i\) 个人第 \(t\) 个时刻还活着,\(\text{Dead}(i,t)\) 则表示第 \(i\) 个人在第 \(t\) 个时刻已经死了,那么题目给出的条件即对应这些布尔变量的一些推导关系,具体来说:
- 由于一个人死了不能复活,所以必有 \(\text{Dead}(i,t)\to\text{Dead}(i,t+1)\),同样地有逆否命题 \(\text{Live}(i,t+1)\to\text{Live}(i,t)\)
- 对于条件 \(0\),显然可以连边 \(\text{Dead}(x,t)\to\text{Dead}(y,t+1)\),同理逆否命题 \(\text{Alive}(y,t+1)\to\text{Alive}(x,t)\)
- 对于条件 \(1\),显然可以连边 \(\text{Alive}(x,t)\to\text{Dead}(y,t)\),同理逆否命题 \(\text{Alive}(y,t)\to\text{Dead}(x,t)\)
那么我们只要对建出来的图跑一遍 Tarjan,那么对于一个 \(i\),可能与它活到 \(T+1\) 时刻的居民数就是 \(n-1\) 再减去满足 \(\text{Alive}(i,T+1)\) 可以推到 \(\text{Dead}(j,T+1)\) 的居民 \(j\) 的数量。注意,如果一个居民 \(j\) 满足 \(\text{Alive}(j,T+1)\) 可以推到 \(\text{Dead}(j,T+1)\),那么它无论如何在 \(T+1\) 时刻都是死亡状态,对于这样的居民我们特判一下即可,具体来说,我们对于每个 \(i\) 去掉 \(\text{Alive}(i,T+1)\) 可以推到 \(\text{Dead}(j,T+1)\) 的点 \(j\) 的数量后,还需去掉满足 \(\text{Alive}(i,T+1)\) 推不到 \(\text{Dead}(j,T+1)\),但 \(\text{Alive}(j,T+1)\) 可以推到 \(\text{Dead}(j,T+1)\) 的 \(j\) 的数量。
这样暴力做空间复杂度是平方的,时间复杂度是三方的,一脸过不去的样子,因此考虑优化,首先可以注意到一件事情就是我们其实并不需要缩点,因为在连出来的这张图中,只存在 \(\text{Alive}\to\text{Alive},\text{Dead}\to\text{Alive},\text{Dead}\to\text{Dead}\) 的边,并且 \(\text{Alive}\) 的边只会从时间后的连向时间前的,\(\text{Dead}\) 的边只会从时间前的连向时间后的,因此原图本身就是一个 DAG。其次,不难发现原图中很多点其实是没有用的,具体来说,我们只需要保留条件中的 \((x,t)\) 和 \((i,T+1)\),其他点都可以去掉,这样点数就降到了 \(\mathcal O(n+m)\),空间复杂度也就降了下来。
但是这样时间复杂度还是会爆炸,不过注意到此题我们只关心两个点之间的可达性,也就是一个取值只有 \(0/1\) 的布尔型变量,因此可以非常自然地想到 bitset,具体来说我们以每个 \((i,T+1)\) 为起点进行一边 DFS 找出它能够到达哪些 \(\text{Dead}(i,T+1)\),用一个 bitset 维护,每次转移就遍历与当前点相邻的点然后令该点的答案或上与其相连的点的答案即可,由于加了记忆化搜索,因此我们每个点最多计算一次,复杂度就是 \(\mathcal O(\dfrac{(n+m)^2}{\omega})\),但这样空间复杂度又爆掉了。因此考虑一个据说非常 common 的套路:分块 DFS,具体来说我们每 \(B\) 个元素一块,然后我们每次处理每一块中的 \(\text{Dead}(i,T+1)\) 对所有点的贡献,这样我们 bitset 的大小只用开到 \(B\),时间复杂度 \(\mathcal O(\dfrac{n^2}{\omega}+\dfrac{n^2}{B})\),空间复杂度 \(\dfrac{nB}{\omega}\),取 \(B=10^4\) 时最优。
const int MAXN=5e4;
const int MAXM=1e5;
const int MAXV=3e5;
const int MAXE=1e6;
const int BLK=1e4;
int n,m,T,ncnt;set<int> nd[MAXN+5];
struct data{int opt,t,x,y;} a[MAXM+5];
map<int,int> id[2][MAXN+5];
int hd[MAXV+5],nxt[MAXE+5],to[MAXE+5],ec=0;
void adde(int u,int v){to[++ec]=v;nxt[ec]=hd[u];hd[u]=ec;}
int lv[MAXN+5],dd[MAXN+5],bel[MAXV+5],res[MAXN+5];
bitset<MAXN+5> must;
bitset<MAXV+5> vis;
bitset<BLK+5> st[MAXV+5];
void dfs(int x,int l,int r){
if(vis.test(x)) return;vis.set(x);st[x].reset();
if(l<=bel[x]&&bel[x]<=r) st[x].set(bel[x]-l+1);
for(int e=hd[x];e;e=nxt[e]){
int y=to[e];dfs(y,l,r);
st[x]|=st[y];
}
}
int main(){
scanf("%d%d%d",&T,&n,&m);
for(int i=1;i<=m;i++) scanf("%d%d%d%d",&a[i].opt,&a[i].t,&a[i].x,&a[i].y);
for(int i=1;i<=n;i++) nd[i].insert(T+1);
for(int i=1;i<=m;i++) nd[a[i].x].insert(a[i].t);
for(int i=1;i<=n;i++){
for(int x:nd[i]) id[0][i][x]=++ncnt,id[1][i][x]=++ncnt;
int pre0=0,pre1=0;
for(int x:nd[i]){
int cur0=id[0][i][x],cur1=id[1][i][x];
if(pre0) adde(pre0,cur0),adde(cur1,pre1);
pre0=cur0;pre1=cur1;
}
}
for(int i=1;i<=m;i++){
if(!a[i].opt){
int tt=*nd[a[i].y].upper_bound(a[i].t);
adde(id[0][a[i].x][a[i].t],id[0][a[i].y][tt]);
adde(id[1][a[i].y][tt],id[1][a[i].x][a[i].t]);
} else {
int tt=*nd[a[i].y].lower_bound(a[i].t);
adde(id[1][a[i].x][a[i].t],id[0][a[i].y][tt]);
adde(id[1][a[i].y][tt],id[0][a[i].x][a[i].t]);
}
}
for(int i=1;i<=n;i++){
lv[i]=id[1][i][T+1];
dd[i]=id[0][i][T+1];bel[dd[i]]=i;
}
for(int l=1,r=BLK;l<=n;l+=BLK,r+=BLK){
chkmin(r,n);vis.reset();bitset<BLK+5> cur;
for(int i=1;i<=n;i++) dfs(lv[i],l,r);
for(int i=l;i<=r;i++) if(st[lv[i]].test(i-l+1)) must.set(i),cur.set(i-l+1);
for(int i=1;i<=n;i++) res[i]+=r-l+1-(st[lv[i]]|cur).count();
}
for(int i=1;i<=n;i++) printf("%d%c",(must.test(i))?0:(res[i]-1)," \n"[i==n]);
return 0;
}
洛谷 P5332 - [JSOI2019]精准预测(2-SAT+bitset+分块处理)的更多相关文章
- [LOJ 3101] [Luogu 5332] [JSOI2019]精准预测(2-SAT+拓扑排序+bitset)
[LOJ 3101] [Luogu 5332] [JSOI2019]精准预测(2-SAT+拓扑排序+bitset) 题面 题面较长,略 分析 首先,发现火星人只有死和活两种状态,考虑2-SAT 建图 ...
- 【JSOI2019】精准预测(2-SAT & bitset)
Description 现有一台预测机,可以预测当前 \(n\) 个人在 \(T\) 个时刻内的生死关系.关系有两种: \(\texttt{0 t x y}\):如果 \(t\) 时刻 \(x\) 死 ...
- [JSOI2019]精准预测
题目 这么明显的限制条件显然是\(\text{2-sat}\) 考虑按照时间拆点,\((0/1,x,t)\)表示\(x\)个人在时间\(t\)是生/死 有一些显然的连边 \[(0,x,t+1)-> ...
- [JSOI2019]精准预测(2-SAT+拓扑排序+bitset)
设第i个人在t时刻生/死为(x,0/1,t),然后显然能够连上(x,0,t)->(x,0,t-1),(x,1,t)->(x,1,t+1),然后对于每个限制,用朴素的2-SAT连边即可. 但 ...
- [Bzoj5285][洛谷P4424][HNOI/AHOI2018]寻宝游戏(bitset)
P4424 [HNOI/AHOI2018]寻宝游戏 某大学每年都会有一次Mystery Hunt的活动,玩家需要根据设置的线索解谜,找到宝藏的位置,前一年获胜的队伍可以获得这一年出题的机会. 作为新生 ...
- 洛谷 - P2257 - YY的GCD - 莫比乌斯反演 - 整除分块
https://www.luogu.org/problemnew/show/P2257 求 \(n,m\) 中 \(gcd(i,j)==p\) 的数对的个数 求 $\sum\limits_p \sum ...
- 洛谷 - UVA11424 - GCD - Extreme (I) - 莫比乌斯反演 - 整除分块
https://www.luogu.org/problemnew/show/UVA11424 原本以为是一道四倍经验题来的. 因为输入的n很多导致像之前那样 \(O(n)\) 计算变得非常荒谬. 那么 ...
- 洛谷P4135 作诗(不一样的分块)
题面 给定一个长度为 n n n 的整数序列 A A A ,序列中每个数在 [ 1 , c ] [1,c] [1,c] 范围内.有 m m m 次询问,每次询问查询一个区间 [ l , r ] [l, ...
- 【LOJ】#3101. 「JSOI2019」精准预测
LOJ#3101. 「JSOI2019」精准预测 设0是生,1是死,按2-sat连边那么第一种情况是\((t,x,1) \rightarrow (t + 1,y,1)\),\((t + 1,y, 0) ...
随机推荐
- [对对子队]发布声明Beta
Beta版本的新功能 新增的游戏内容 循环部分关卡 Beta阶段我们制作了游戏的第4-6关,为循环部分关卡.这一部分的关卡设计以编程的循环思想为基础,在流水线中加入了新的命令--循环语句,并以此为核心 ...
- [火星补锅] siano 神奇的线段树
前言: 本来以为很难打的,没想到主干一次就打对了,然而把输入的b和d弄混了,这sb错误调了两个小时... 解析: 神奇的线段树.注意到有一个性质,无论怎么割草,生长速度快的一定不会比生长速度慢的矮.因 ...
- 最详细的windows10系统封装教程
目录 自定义封装(定制)windows10教程 关于本教程及用到的工具的声明 第一阶段: 封装前的各种环境准备 安装vmware 创建虚拟机 对虚拟机进行分区 配置好BIOS 为虚拟机安装window ...
- udev 使用方法
原文地址 http://blog.163.com/againinput4@yeah/blog/static/122764271200962305339483/ 最近有在研究SD卡设备节点自动创建及挂载 ...
- K8s 离线集群部署(二进制包无dashboard)
https://www.cnblogs.com/cocowool/p/install_k8s_offline.html https://www.jianshu.com/p/073577bdec98 h ...
- 力扣 - 剑指 Offer 67. 把字符串转换成整数
题目 剑指 Offer 67. 把字符串转换成整数 思路1 根据题意,要解决这题,首先要判断的条件有: 不包括首位空格 第一位必须为:+.-.数字三者其一,否则不合法 数字必须连续的,如果遇到非数字, ...
- vue+elementUI中单选框el-radio设置默认值和唯一标识某个单选框
vue+elementUI中单选框el-radio设置默认值 如果后台返回的单选框的值是number:单选框的lable需要设置成 :lable='0';如下: <el-form-item la ...
- Mybatis:插入数据返回自增主键
使用Mybatis作为工具连接MySQL,要求在插入数据之后返回自增主键 一开始也很迷惑,Mybatis使用insert之后,成功返回的是1,失败会报错或返回0,主键去哪找来 后来知道Mybatis可 ...
- Part 29 AngularJS intellisense in visual studio
In the previous videos if you have noticed as we were typing the angular code in Script.js file we w ...
- 分布式配置系统Apollo如何实时更新配置的?
引言 记得我们那时候刚开始学习Java的时候都只是一个单体项目,项目里面的配置基本都是写在项目里面的properties文件中,比如数据库配置啥的,各种逻辑开关,一旦这些配置修改了,还需要重启项目这修 ...