結果

問題 No.1914 Directed by Two Sequences
ユーザー chineristAC
提出日時 2021-11-05 20:14:43
言語 PyPy3
(7.3.15)
結果
WA  
実行時間 -
コード長 10,299 bytes
コンパイル時間 167 ms
コンパイル使用メモリ 82,304 KB
実行使用メモリ 171,672 KB
最終ジャッジ日時 2024-12-16 01:35:34
合計ジャッジ時間 52,745 ms
ジャッジサーバーID
(参考情報)
judge3 / judge1
このコードへのチャレンジ
(要ログイン)
ファイルパターン 結果
sample WA * 2
other AC * 1 WA * 37
権限があれば一括ダウンロードができます

ソースコード

diff #
プレゼンテーションモードにする

"""
WA
"""
class SegmentTree:
def __init__(self, init_val, segfunc, ide_ele):
n = len(init_val)
self.segfunc = segfunc
self.ide_ele = ide_ele
self.num = 1 << (n - 1).bit_length()
self.tree = [ide_ele] * 2 * self.num
self.size = n
for i in range(n):
self.tree[self.num + i] = init_val[i]
for i in range(self.num - 1, 0, -1):
self.tree[i] = self.segfunc(self.tree[2 * i], self.tree[2 * i + 1])
def update(self, k, x):
k += self.num
self.tree[k] = x
while k > 1:
k >>= 1
self.tree[k] = self.segfunc(self.tree[2*k], self.tree[2*k+1])
def query(self, l, r):
if r==self.size:
r = self.num
res = self.ide_ele
l += self.num
r += self.num
right = []
while l < r:
if l & 1:
res = self.segfunc(res, self.tree[l])
l += 1
if r & 1:
right.append(self.tree[r-1])
l >>= 1
r >>= 1
for e in right[::-1]:
res = self.segfunc(res,e)
return res
class _csr:
def __init__(self, n, edges):
self.start = [0] * (n + 1)
self.elist = [0] * len(edges)
for v, _ in edges:
self.start[v + 1] += 1
for i in range(1, n + 1):
self.start[i] += self.start[i - 1]
counter = self.start.copy()
for v, e in edges:
self.elist[counter[v]] = e
counter[v] += 1
class scc_graph:
"""It calculates the strongly connected components of directed graphs.
"""
def __init__(self, n):
"""It creates a directed graph with n vertices and 0 edges.
Constraints
-----------
> 0 <= n <= 10 ** 8
Complexity
----------
> O(n)
"""
self.n = n
self.edges = []
def add_edge(self, from_, to):
"""It adds a directed edge from the vertex `from_` to the vertex `to`.
Constraints
-----------
> 0 <= from_ < n
> 0 <= to < n
Complexity
----------
> O(1) amortized
"""
# assert 0 <= from_ < self.n
# assert 0 <= to < self.n
self.edges.append((from_, to))
def _scc_ids(self):
g = _csr(self.n, self.edges)
now_ord = 0
group_num = 0
visited = []
low = [0] * self.n
order = [-1] * self.n
ids = [0] * self.n
parent = [-1] * self.n
stack = []
for i in range(self.n):
if order[i] == -1:
stack.append(i)
stack.append(i)
while stack:
v = stack.pop()
if order[v] == -1:
low[v] = order[v] = now_ord
now_ord += 1
visited.append(v)
for i in range(g.start[v], g.start[v + 1]):
to = g.elist[i]
if order[to] == -1:
stack.append(to)
stack.append(to)
parent[to] = v
else:
low[v] = min(low[v], order[to])
else:
if low[v] == order[v]:
while True:
u = visited.pop()
order[u] = self.n
ids[u] = group_num
if u == v:
break
group_num += 1
if parent[v] != -1:
low[parent[v]] = min(low[parent[v]], low[v])
for i, x in enumerate(ids):
ids[i] = group_num - 1 - x
return group_num, ids
def scc(self):
"""It returns the list of the "list of the vertices" that satisfies the following.
> Each vertex is in exactly one "list of the vertices".
> Each "list of the vertices" corresponds to the vertex set of a strongly connected component.
The order of the vertices in the list is undefined.
> The list of "list of the vertices" are sorted in topological order,
i.e., for two vertices u, v in different strongly connected components,
if there is a directed path from u to v,
the list contains u appears earlier than the list contains v.
Complexity
----------
> O(n + m), where m is the number of added edges.
"""
group_num, ids = self._scc_ids()
groups = [[] for _ in range(group_num)]
for i, x in enumerate(ids):
groups[x].append(i)
return groups
def popcount(x):
'''x
(x64bit)'''
# 2bit2bit
x = x - ((x >> 1) & 0x5555555555555555)
# 4bit 2bit + 2bit
x = (x & 0x3333333333333333) + ((x >> 2) & 0x3333333333333333)
x = (x + (x >> 4)) & 0x0f0f0f0f0f0f0f0f # 8bit
x = x + (x >> 8) # 16bit
x = x + (x >> 16) # 32bit
x = x + (x >> 32) # 64bit =
return x & 0x0000007f
popcnt = [popcount(i) for i in range(2**20)]
def solve(N,A,B,M,E):
A = [a-1 for a in A]
B = [b-1 for b in B]
G = scc_graph(N)
edge = [[] for v in range(N)]
for u,v in E:
edge[u-1].append(v-1)
edge[v-1].append(u-1)
group = [-1 for v in range(N)]
for v in range(N):
mex = [False for i in range(len(edge[v])+1)]
for nv in edge[v]:
if nv < v and group[nv] < len(mex):
mex[group[nv]] = True
for i in range(len(mex)):
if not mex[i]:
group[v] = i
break
n = max(group) + 1
clique = [[] for g in range(n)]
for v in range(N):
clique[group[v]].append(v)
def direct(i,j):
if i < j:
return A[i] < B[j]
else:
return B[i] < A[j]
def hamilton_path(V):
n = len(V)
if n <= 1:
return V
A = hamilton_path(V[:n//2])
B = hamilton_path(V[n//2:])
res = []
bi = 0
for ai in range(len(A)):
while bi<len(B) and direct(B[bi],A[ai]):
res.append(B[bi])
bi += 1
res.append(A[ai])
res += B[bi:]
return res
idx = [-1 for v in range(N)]
for g in range(n):
clique[g] = hamilton_path(clique[g])
for i in range(len(clique[g])):
idx[clique[g][i]] = i
for u,v in zip(clique[g],clique[g][1:]):
G.add_edge(u,v)
memo_to = [N for v in range(N)]
memo_from = [-1 for v in range(N)]
ci = [i for i in range(n)]
ci.sort(lambda g:len(clique[g]))
idx_on_ci = [-1 for i in range(n)]
for i in range(n):
idx_on_ci[ci[i]] = i
ban = [[] for v in range(N)]
Vs = []
seg_to_large = SegmentTree([N]*2*N,min,N)
seg_to_small = SegmentTree([N]*2*N,min,N)
seg_from_large = SegmentTree([-1]*2*N,max,-1)
seg_from_small = SegmentTree([-1]*2*N,max,-1)
for i in range(n):
target = ci[i]
Vs += clique[target]
Vs.sort()
for nv in clique[target]:
for v in edge[nv]:
if idx_on_ci[group[v]] <= i:
ban[v].append(nv)
for v in Vs[::-1]:
for nv in ban[v]:
if v < nv:
seg_to_large.update(B[nv],N)
memo_to[v] = min(memo_to[v],seg_to_large.query(A[v],2*N))
for nv in ban[v]:
if v < nv:
seg_to_large.update(B[nv],idx[nv])
if group[v]==target:
seg_to_large.update(B[v],idx[v])
for v in Vs:
for nv in ban[v]:
if nv < v:
seg_to_small.update(A[nv],N)
memo_to[v] = min(memo_to[v],seg_to_small.query(B[v],2*N))
for nv in ban[v]:
if nv < v:
seg_to_small.update(A[nv],idx[nv])
if group[v]==target:
seg_to_small.update(A[v],idx[v])
for v in Vs[::-1]:
for nv in ban[v]:
if v < nv:
seg_from_large.update(B[nv],-1)
memo_from[v] = max(memo_from[v],seg_from_large.query(0,A[v]))
for nv in ban[v]:
if v < nv:
seg_from_large.update(B[nv],idx[nv])
if group[v]==target:
seg_from_large.update(B[v],idx[v])
for v in Vs:
for nv in ban[v]:
if nv < v:
seg_from_small.update(A[nv],-1)
memo_from[v] = max(memo_from[v],seg_from_small.query(0,B[v]))
for nv in ban[v]:
if nv < v:
seg_from_small.update(A[nv],idx[nv])
if group[v]==target:
seg_from_small.update(A[v],idx[v])
for v in Vs:
if memo_to[v]!=N:
nv = clique[target][memo_to[v]]
G.add_edge(v,nv)
memo_to[v] = N
if memo_from[v]!=-1:
pv = clique[target][memo_from[v]]
G.add_edge(pv,v)
memo_from[v] = -1
ban[v] = []
if group[v]==target:
seg_to_large.update(B[v],N)
seg_to_small.update(A[v],N)
seg_from_large.update(B[v],-1)
seg_from_small.update(A[v],-1)
group_num,ids = G._scc_ids()
res = [(i+1,i+2) for i in range(N-1)] + [(N,1)]
print(len(res))
for u,v in res:
print(u,v)
import sys
input = lambda :sys.stdin.buffer.readline()
mi = lambda :map(int,input().split())
li = lambda :list(mi())
N,M = mi()
A = li()
B = li()
E = [tuple(mi()) for i in range(M)]
solve(N,A,B,M,E)
הההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההה
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
0