CF1889D Game of Stacks 题解

link T3です

nn 个整数栈 s1,s2,,sns_1, s_2, \dots, s_n

对于一个初始值 pp,令 xpx_psps_p 的栈顶,更新 pxpp\leftarrow x_p,直到 sps_p 为空。

对每个 p=1,2,,np = 1, 2, \dots, n,求最终的 pp 值。


优雅。

先考虑栈大小为 11 的情况。

我们考虑直接转化为图论模型。即连边 ixii\rightarrow x_i

注意到这里实际上是一个内向基环树。那么对于任意出发点 pp 而言,结果就为走到环上的第一个点。

乍看没有什么启发性。因为栈大小 >1>1 的情况很难建图。

但注意到对于基环树的情况,我们实际上可以忽略环

容易发现,一个环上的所有点转一圈也都是回到自己的点。就说明忽略环对所有 pp 不会影响正确性。

这个东西也可以应用到栈大小 >1>1 的情况:

考虑对每个 pp 跑一遍,在跑的过程中遇到的环是可以直接从栈里面抹除的。那么抹除了所有环之后这些栈构成的边就会变成一棵树。直接在树上跑一遍即可。

分析一下复杂度。O(k+n2)O(\sum k+n^2),咦,超了。

这里复杂度有 O(n2)O(n^2) 的原因是每个点都有可能遍历一遍整棵树。

那么我们可以考虑 ppansp=tans_p=t,显然 pp 在树上经过的点最后的结果都为 tt。只对没有 ansans 的位置访问和转移即可。

代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
int n;
vector<int> a[maxn];
void input(){
n=read();
for(int i=1;i<=n;++i){
int len=read();
a[i].emplace_back(0);
for(int j=1;j<=len;++j){
a[i].emplace_back(read());
}
}
}

int ans[maxn];

int vis[maxn],top[maxn];
int tim;
stack<pair<int,int> > fix;//在时间tim修改了哪个位置
int go(int st){
int x=st;
while(1){
vis[x]=++tim;
fix.push({tim,x});

int nxt=a[x][top[x]];
--top[x];
if(ans[nxt]) return ans[nxt];
if(vis[nxt]){
int previstim=vis[nxt];
while(fix.size()&&fix.top().first>=previstim){
int p=fix.top().second;
a[p].pop_back();//至于这里为什么可以直接 pop_back 看下面
vis[p]=0;
fix.pop();
}
tim=previstim-1;
}
if(nxt==0) return x;
x=nxt;
}
}
void solve(){
for(int i=1;i<=n;++i){
top[i]=a[i].size()-1;
}
for(int i=1;i<=n;++i){
if(!ans[i]){
int endp=go(i);
while(fix.size()){
int p=fix.top().second;
++top[p];
ans[p]=endp;
vis[p]=0;
fix.pop();
}
tim=0;
}
}
for(int i=1;i<=n;++i) printf("%d ",ans[i]);
}

int main(){
input();
solve();
return 0;
}

关于为什么可以直接 pop_back (上面只是讲到在栈里面抹除没说抹除的就是最上面的对吧),考虑以下情况:

在没有环消去前,显然的,消去的环一定是在第一层,可以直接用 pop_back

在第一个环消去后,考虑消去的位置直接补齐第一层。那这样子下一个消去的环就又在第一层了。推广到第 nn 个环消去后即可。

然后就可以以 O(k+n)O(\sum k+n) 的复杂度优雅地过掉了。

sub


附:抄了这篇题解


CF1889D Game of Stacks 题解
https://formu1-github.github.io/Hexo-blog/2025/10/21/CF1889D-Game-of-Stacks-题解/
作者
Formu1
发布于
2025年10月21日
许可协议