restructure, slow security solution
This commit is contained in:
42
asecbadge.py
Normal file
42
asecbadge.py
Normal file
@@ -0,0 +1,42 @@
|
||||
from collections import deque, defaultdict
|
||||
from intset import IntSet
|
||||
|
||||
N, L, B = map(int, input().split())
|
||||
|
||||
S, D = map(int, input().split())
|
||||
|
||||
rooms = defaultdict(dict)
|
||||
|
||||
ALL = IntSet(1, B + 1)
|
||||
NONE = IntSet()
|
||||
|
||||
for i in range(L):
|
||||
a, b, x, y = map(int, input().split())
|
||||
rooms[a][b] = IntSet(x, y + 1)
|
||||
|
||||
ranges = defaultdict(lambda: NONE)
|
||||
ranges[S] = ALL
|
||||
|
||||
q = deque([S])
|
||||
|
||||
while q:
|
||||
if len(ranges[D]) == B:
|
||||
break
|
||||
|
||||
curr = q.pop()
|
||||
|
||||
# if curr == D:
|
||||
# continue
|
||||
|
||||
for neighbor, r in rooms[curr].items():
|
||||
old = ranges[neighbor]
|
||||
new = ranges[neighbor] | ranges[curr] & r
|
||||
if old != new:
|
||||
# try:
|
||||
# q.remove(neighbor)
|
||||
# except ValueError:
|
||||
# pass
|
||||
q.append(neighbor)
|
||||
ranges[neighbor] = new
|
||||
|
||||
print(len(ranges[D]))
|
||||
42
asecbadge_back.py
Normal file
42
asecbadge_back.py
Normal file
@@ -0,0 +1,42 @@
|
||||
from collections import deque, defaultdict
|
||||
from intset import IntSet
|
||||
|
||||
N, L, B = map(int, input().split())
|
||||
|
||||
S, D = map(int, input().split())
|
||||
|
||||
rooms = defaultdict(dict)
|
||||
|
||||
ALL = IntSet(1, B + 1)
|
||||
NONE = IntSet()
|
||||
|
||||
for i in range(L):
|
||||
a, b, x, y = map(int, input().split())
|
||||
rooms[b][a] = IntSet(x, y + 1)
|
||||
|
||||
ranges = defaultdict(lambda: NONE)
|
||||
ranges[D] = ALL
|
||||
|
||||
q = [D]
|
||||
|
||||
while q:
|
||||
# if len(ranges[D]) == B:
|
||||
# break
|
||||
|
||||
curr = q.pop(0)
|
||||
|
||||
# if curr == D:
|
||||
# continue
|
||||
|
||||
for neighbor, r in rooms[curr].items():
|
||||
old = ranges[neighbor]
|
||||
new = ranges[neighbor] | (ranges[curr] & r)
|
||||
if len(old) != len(new):
|
||||
# try:
|
||||
# q.remove(neighbor)
|
||||
# except ValueError:
|
||||
# pass
|
||||
q.append(neighbor)
|
||||
ranges[neighbor] = new
|
||||
|
||||
print(len(ranges[S]))
|
||||
50
asecbadge_iter.py
Normal file
50
asecbadge_iter.py
Normal file
@@ -0,0 +1,50 @@
|
||||
from collections import deque, defaultdict
|
||||
|
||||
N, L, B = map(int, input().split())
|
||||
|
||||
S, D = map(int, input().split())
|
||||
|
||||
rooms = defaultdict(dict)
|
||||
|
||||
bounds = set()
|
||||
|
||||
for _ in range(L):
|
||||
a, b, x, y = map(int, input().split())
|
||||
rooms[a][b] = x, y + 1
|
||||
bounds.add(x)
|
||||
bounds.add(y + 1)
|
||||
|
||||
total = 0
|
||||
|
||||
bounds = sorted(bounds)
|
||||
|
||||
|
||||
def piecewise(seq):
|
||||
it = iter(seq)
|
||||
last = next(it)
|
||||
for new in it:
|
||||
yield last, new
|
||||
last = new
|
||||
|
||||
|
||||
for a, b in piecewise(bounds):
|
||||
q = deque([S])
|
||||
visited = [0] * L
|
||||
|
||||
while q:
|
||||
curr = q.pop()
|
||||
visited[curr - 1] = 1
|
||||
nbors = rooms[curr].items()
|
||||
|
||||
if curr == D:
|
||||
total += b - a
|
||||
break
|
||||
|
||||
for n, (la, lb) in nbors:
|
||||
if visited[n - 1]:
|
||||
continue
|
||||
|
||||
if a >= la and b <= lb:
|
||||
q.append(n)
|
||||
|
||||
print(total)
|
||||
111
intset.py
Normal file
111
intset.py
Normal file
@@ -0,0 +1,111 @@
|
||||
class IntSet:
|
||||
def __init__(self, *bounds):
|
||||
"""Bounds must be tuples of the form (a, b),
|
||||
where integers a <= x < b are included in the set.
|
||||
"""
|
||||
|
||||
if not bounds:
|
||||
bounds = [0, 0]
|
||||
|
||||
self.bounds = list(bounds)
|
||||
|
||||
def simplify(self):
|
||||
i = 0
|
||||
while i < len(self.bounds) - 1:
|
||||
if i % 2 == 0:
|
||||
if self.bounds[i] >= self.bounds[i + 1]:
|
||||
del self.bounds[i:i + 2]
|
||||
else:
|
||||
i += 1
|
||||
else:
|
||||
if self.bounds[i] >= self.bounds[i + 1]:
|
||||
if self.bounds[i] >= self.bounds[i + 2]:
|
||||
del self.bounds[i + 1:i + 3]
|
||||
else:
|
||||
del self.bounds[i:i + 2]
|
||||
else:
|
||||
i += 1
|
||||
|
||||
def __or__(self, other):
|
||||
bounds = None
|
||||
j = k = 0
|
||||
|
||||
while j < len(self.bounds) - 1 or k < len(other.bounds) - 1:
|
||||
if k >= len(other.bounds) - 1:
|
||||
a, b = self.bounds[j:j + 2]
|
||||
j += 2
|
||||
elif j >= len(self.bounds) - 1:
|
||||
a, b = other.bounds[k:k + 2]
|
||||
k += 2
|
||||
elif self.bounds[j] < other.bounds[k]:
|
||||
a, b = self.bounds[j:j + 2]
|
||||
j += 2
|
||||
else:
|
||||
a, b = other.bounds[k:k + 2]
|
||||
k += 2
|
||||
|
||||
if a >= b:
|
||||
continue
|
||||
|
||||
if not bounds:
|
||||
bounds = [a, b]
|
||||
continue
|
||||
|
||||
e = bounds[-1]
|
||||
|
||||
if e >= a:
|
||||
if e >= b:
|
||||
continue
|
||||
bounds[-1] = b
|
||||
else:
|
||||
bounds.append(a)
|
||||
bounds.append(b)
|
||||
|
||||
if not bounds:
|
||||
bounds = [0, 0]
|
||||
|
||||
new = IntSet()
|
||||
new.bounds = bounds
|
||||
return new
|
||||
|
||||
def __and__(self, other):
|
||||
bounds = []
|
||||
|
||||
i = j = 0
|
||||
while i < len(self.bounds) - 1 and j < len(other.bounds) - 1:
|
||||
a, b = self.bounds[i:i + 2]
|
||||
c, d = other.bounds[j:j + 2]
|
||||
if b > c and a < d:
|
||||
bounds.append(max(a, c))
|
||||
bounds.append(min(b, d))
|
||||
if b < d:
|
||||
i += 2 # toss a b
|
||||
else:
|
||||
j += 2 # toss c d
|
||||
|
||||
new = IntSet()
|
||||
new.bounds = bounds
|
||||
new.simplify()
|
||||
return new
|
||||
|
||||
def __eq__(self, other):
|
||||
return self.bounds == other.bounds
|
||||
|
||||
def __iter__(self):
|
||||
for a, b in self.pairs:
|
||||
yield from range(a, b)
|
||||
|
||||
def __len__(self):
|
||||
return sum(b - a if b > a else 0 for a, b in self.pairs)
|
||||
|
||||
def __lt__(self, other):
|
||||
return len(self) < len(other)
|
||||
|
||||
@property
|
||||
def pairs(self):
|
||||
it = iter(self.bounds)
|
||||
while True:
|
||||
yield next(it), next(it)
|
||||
|
||||
def __repr__(self):
|
||||
return 'U'.join('[{0},{1})'.format(a, b) for a, b in self.pairs)
|
||||
4
make_and_test.py
Normal file
4
make_and_test.py
Normal file
@@ -0,0 +1,4 @@
|
||||
import subprocess
|
||||
|
||||
subprocess.call(['python', 'make_nonsense.py'])
|
||||
subprocess.call(['python', 'icpc_test.py', 'asecbadge_multi.py', 'security', '5'])
|
||||
22
make_nonsense.py
Normal file
22
make_nonsense.py
Normal file
@@ -0,0 +1,22 @@
|
||||
from itertools import islice, permutations
|
||||
from random import randint, sample
|
||||
|
||||
N, L, B = 1000, 5000, 100_000_000
|
||||
S = D = 0
|
||||
while S == D:
|
||||
S, D = randint(1, N), randint(1, N)
|
||||
|
||||
pairs = sample(list(permutations(range(N), r=2)), L)
|
||||
rows = []
|
||||
|
||||
for a, b in pairs:
|
||||
x = randint(1, B)
|
||||
y = randint(x, B)
|
||||
|
||||
rows.append((a, b, x, y))
|
||||
|
||||
with open('test/security/nonsense.in', 'w') as f:
|
||||
f.writelines(' '.join(map(str, tup)) + '\n' for tup in [(N, L, B), (S, D)] + rows)
|
||||
|
||||
with open('test/security/nonsense.ans', 'w') as f:
|
||||
f.write('27\n')
|
||||
57
secbadge.py
57
secbadge.py
@@ -1,57 +0,0 @@
|
||||
##N, L, B = input().strip().split()
|
||||
##S, D = input().strip().split()
|
||||
|
||||
class Range():
|
||||
|
||||
def __init__(self, ranges):
|
||||
self.ranges = ranges
|
||||
|
||||
def __add__(self, other):
|
||||
new_ranges = list(self.ranges)
|
||||
for rang1 in other.ranges:
|
||||
for i, rang2 in enumerate(new_ranges):
|
||||
if rang1[0] <= rang2[0] and rang1[1] >= rang2[1]:
|
||||
new_ranges[i] = rang1
|
||||
break
|
||||
if rang1[0] >= rang2[0] and rang1[1] <= rang2[1]:
|
||||
break
|
||||
if rang1[1] >= rang2[0]-1 and rang1[1] <= rang2[1]:
|
||||
new_ranges[i] = (rang1[0], rang2[1])
|
||||
break
|
||||
if rang1[0] >= rang2[0] and rang1[0] <= rang2[1]+1:
|
||||
new_ranges[i] = (rang2[0], rang1[1])
|
||||
break
|
||||
else:
|
||||
new_ranges.append(rang1)
|
||||
return Range(new_ranges)
|
||||
|
||||
def __mul__(self, other):
|
||||
new_ranges = []
|
||||
for rang1 in other.ranges:
|
||||
cand = rang1
|
||||
for rang2 in self.ranges:
|
||||
if rang1[0] <= rang2[0] and rang1[1] >= rang2[1]:
|
||||
cand = rand2
|
||||
elif rang1[0] >= rang2[0] and rang1[1] <= rang2[1]:
|
||||
pass
|
||||
elif rang1[1] >= rang2[0] and rang1[1] <= rang2[1]:
|
||||
cand (rang2[0], rang1[1])
|
||||
elif rang1[0] >= rang2[0] and rang1[0] <= rang2[1]:
|
||||
cand = (rang1[0], rang2[1])
|
||||
else:
|
||||
break
|
||||
else:
|
||||
new_ranges.append(cand)
|
||||
return Range(new_ranges)
|
||||
|
||||
def __repr__(self):
|
||||
return str(*self.ranges)
|
||||
|
||||
def __str__(self):
|
||||
return str(self.ranges)
|
||||
|
||||
Range.INF = Range([(-float('inf'), float('inf'))])
|
||||
|
||||
a = Range.INF
|
||||
b = Range([(3, 4)])
|
||||
print(a+b)
|
||||
1
test/security/custom_1.ans
Normal file
1
test/security/custom_1.ans
Normal file
@@ -0,0 +1 @@
|
||||
10
|
||||
6
test/security/custom_1.in
Normal file
6
test/security/custom_1.in
Normal file
@@ -0,0 +1,6 @@
|
||||
3 4 10
|
||||
1 3
|
||||
1 3 1 5
|
||||
1 2 6 10
|
||||
2 3 6 10
|
||||
3 2 6 10
|
||||
1
test/security/custom_2.ans
Normal file
1
test/security/custom_2.ans
Normal file
@@ -0,0 +1 @@
|
||||
0
|
||||
5
test/security/custom_2.in
Normal file
5
test/security/custom_2.in
Normal file
@@ -0,0 +1,5 @@
|
||||
4 3 10
|
||||
1 4
|
||||
1 3 1 5
|
||||
1 2 6 10
|
||||
2 3 6 10
|
||||
Reference in New Issue
Block a user