洛谷题面传送门

七月份(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+分块处理)的更多相关文章

  1. [LOJ 3101] [Luogu 5332] [JSOI2019]精准预测(2-SAT+拓扑排序+bitset)

    [LOJ 3101] [Luogu 5332] [JSOI2019]精准预测(2-SAT+拓扑排序+bitset) 题面 题面较长,略 分析 首先,发现火星人只有死和活两种状态,考虑2-SAT 建图 ...

  2. 【JSOI2019】精准预测(2-SAT & bitset)

    Description 现有一台预测机,可以预测当前 \(n\) 个人在 \(T\) 个时刻内的生死关系.关系有两种: \(\texttt{0 t x y}\):如果 \(t\) 时刻 \(x\) 死 ...

  3. [JSOI2019]精准预测

    题目 这么明显的限制条件显然是\(\text{2-sat}\) 考虑按照时间拆点,\((0/1,x,t)\)表示\(x\)个人在时间\(t\)是生/死 有一些显然的连边 \[(0,x,t+1)-> ...

  4. [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连边即可. 但 ...

  5. [Bzoj5285][洛谷P4424][HNOI/AHOI2018]寻宝游戏(bitset)

    P4424 [HNOI/AHOI2018]寻宝游戏 某大学每年都会有一次Mystery Hunt的活动,玩家需要根据设置的线索解谜,找到宝藏的位置,前一年获胜的队伍可以获得这一年出题的机会. 作为新生 ...

  6. 洛谷 - P2257 - YY的GCD - 莫比乌斯反演 - 整除分块

    https://www.luogu.org/problemnew/show/P2257 求 \(n,m\) 中 \(gcd(i,j)==p\) 的数对的个数 求 $\sum\limits_p \sum ...

  7. 洛谷 - UVA11424 - GCD - Extreme (I) - 莫比乌斯反演 - 整除分块

    https://www.luogu.org/problemnew/show/UVA11424 原本以为是一道四倍经验题来的. 因为输入的n很多导致像之前那样 \(O(n)\) 计算变得非常荒谬. 那么 ...

  8. 洛谷P4135 作诗(不一样的分块)

    题面 给定一个长度为 n n n 的整数序列 A A A ,序列中每个数在 [ 1 , c ] [1,c] [1,c] 范围内.有 m m m 次询问,每次询问查询一个区间 [ l , r ] [l, ...

  9. 【LOJ】#3101. 「JSOI2019」精准预测

    LOJ#3101. 「JSOI2019」精准预测 设0是生,1是死,按2-sat连边那么第一种情况是\((t,x,1) \rightarrow (t + 1,y,1)\),\((t + 1,y, 0) ...

随机推荐

  1. Linux上传下载神器之 lrzsz

    在开发的过程中,经常遇到 需要在 Linux 和 Windows 之间上传下载文件的情况 这时,一般都是使用 FTP 或者 WinSCP 工具进行上传下载, 虽然也能解决问题,但是这些工具需要在本地安 ...

  2. kivy Label触发事件

    kivy  label也可以触发事件,为什么只有我这么无聊学垃圾kivy """ 在通过ref标记一段文本后点击这段文本就可以触发'on_ref_press'事件,在该事 ...

  3. OO第四单元

    OO第四单元总结 第四单元架构设计 第一次作业 uml类图 这次作业我采取的基本思路就是根据指令来建造一个简易的类图,用于查询,其中umlclass中包含了umlAttraibute,umlOpera ...

  4. 冲刺noip2021模拟16

    T1 树上的数 考场上比较脑瘫没有想到直接dfs就行了这样是O(n+m)的,傻不拉几地多添了个log, 不过因为accoder的评测机太弱了,绝大多数人的正解都是60分,所以没有什么差别: 直接dfs ...

  5. vcs命令

    转载:VCS_weixin_34256074的博客-CSDN博客 timing check相关的: +notimingcheck命令,可以用在compile时,也可以用在run time的时候, 都是 ...

  6. Python import cStringIO ImportError: No module named 'cStringIO'

    From Python 3.0 changelog; The StringIO and cStringIO modules are gone. Instead, import the io modul ...

  7. 从零开始,无DNS vcenter 6.7 vmotion热迁移,存储集群部署文档。

    1,环境准备 准备:Vmware workstation环境 IP地址段规划 ESXI主机IP地址段 192.168.197.4-192.168.197.10 Vcenter Server集群IP地址 ...

  8. sprint boot 自动创建web应用(3)

    1. springboot自动创建地址:https://start.spring.io/ 2.选择web(springMVC) 3.点击创建 4.创建成功 5.解压,导入项目 6.新建成功 7.原因 ...

  9. 1.在项目中使用D3.js

    在项目中使用D3.js D3.js(全称:Data-Driven Documents)是一个基于数据操作文档的JavaScript库.D3帮助您使用HTML.SVG和CSS使数据生动起来.D3对web ...

  10. appium环境搭建基于安卓(mac系统)

    1.需要环境 JDK Python Andriod SDK Node.js Appium Appium-Python-Client Appium-doctor 2.安装jdk(我的版本是1.8) 下载 ...