日志统计
小明维护着一个程序员论坛。现在他收集了一份”点赞”日志,日志共有 N 行。
其中每一行的格式是:
ts id
表示在 ts 时刻编号 id 的帖子收到一个”赞”。
现在小明想统计有哪些帖子曾经是”热帖”。
如果一个帖子曾在任意一个长度为 D 的时间段内收到不少于 K 个赞,小明就认为这个帖子曾是”热帖”。
具体来说,如果存在某个时刻 T 满足该帖在 [T,T+D) 这段时间内(注意是左闭右开区间)收到不少于 K 个赞,该帖就曾是”热帖”。
给定日志,请你帮助小明统计出所有曾是”热帖”的帖子编号。
输入格式
第一行包含三个整数 N,D,K。
以下 N 行每行一条日志,包含两个整数 ts 和 id。
输出格式
按从小到大的顺序输出热帖 id。
每个 id 占一行。
数据范围
1≤K≤N≤105,
0≤ts,id≤105,
1≤D≤10000
输入样例:
7 10 2
0 1
0 10
10 10
10 1
9 1
100 3
100 3
输出样例:
1
3
把所有日志按照时间先后顺序排序,然后利用双指针法,维护一个长度为 D 的区间,当存在点赞数大于等于 K 的帖子时,就将它记录下来
IA = lambda:map(int, input().split())
N = 1000010
n, d, k = IA()
a = [[0,0] for i in range(n)]
for i in range(n):
a[i][0], a[i][1] = IA()
a.sort()
l = 0
r = 0
cnt = [0 for i in range(N)]
st = [0 for i in range(N)]
while r < n:
cnt[a[r][1]] += 1
while a[r][0] - a[l][0] >= d:
cnt[a[l][1]] -= 1
l += 1
if cnt[a[r][1]] >= k:
st[a[r][1]] = 1
r += 1
for i in range(N):
if st[i] == 1:
print(i)
合法三元组的个数
输入格式
第一行包含四个整数 lA,lB,lC,dlA,lB,lC,d,分别表示数组 A,B,CA,B,C 的长度以及给定非负整数。
第二行包含 lAlA 个整数 A0,A1,…,AlA−1A0,A1,…,AlA−1,用来描述数组 AA。
第三行包含 lBlB 个整数 B0,B1,…,BlB−1B0,B1,…,BlB−1,用来描述数组 BB。
第四行包含 lClC 个整数 C0,C1,…,ClC−1C0,C1,…,ClC−1,用来描述数组 CC。
输出格式
输出一个整数,用来表示满足条件的三元组的个数。
数据范围
1≤lA,lB,lC≤1051≤lA,lB,lC≤105,
0≤d≤1090≤d≤109,
三个数组中的元素的取值范围为 [−109,109][−109,109]。
输入样例:
3 3 3 2
1 3 5
2 4 6
3 5 7
输出样例:
8
根据题意可知 三元组的最大元素和最小元素之差为d,可以将所有元素放到一个数组里。
维护一个窗口大小为d的窗口,每次答案增加 窗口中属于a的个属于b的个数属于c的个数
需要注意在窗口滑动过程中会出现重复计算,例如第一次窗口为[0,6] 第二次窗口为[3,7],那么[3,6]这段会被重复计算,需要减去。
IA = lambda:map(int, input().split())
n, m, k, d = IA()
a = list(IA())
b = list(IA())
c = list(IA())
x = []
for i in range(n):
x.append([a[i], 1])
for i in range(m):
x.append([b[i], 2])
for i in range(k):
x.append([c[i], 3])
x.sort()
l = 0
r = 0
N = max(max(a), max(b), max(c))
cnt = [0, 0, 0, 0]
res = 0
while r < n + m+ k:
while x[r][0] - x[l][0] > d:
cnt[x[l][1]] -= 1
l += 1
res -= cnt[1] * cnt[2] * cnt[3]
cnt[x[r][1]] += 1
res += cnt[1] * cnt[2] * cnt[3]
r += 1
print(res)
递增三元组
给定三个整数数组
A=[A1,A2,…AN],
B=[B1,B2,…BN],
C=[C1,C2,…CN],
请你统计有多少个三元组 (i,j,k) 满足:
1≤i,j,k≤N 输入格式 第二行包含 N 个整数 A1,A2,…AN。 第三行包含 N 个整数 B1,B2,…BN。 第四行包含 N 个整数 C1,C2,…CN。 输出格式 数据范围 样例 3 27 要求满足Ai 要求满足Ai 进一步对查找进行优化,对于排过序的数组A和B,寻找A中小于B[i]的元素的个数可以考虑双指针算法,因为每个指针最多移动n次,故查找的时间复杂度降到O(n),查找C与查找A同理,只是找第一个大于B的位置。
Ai
第一行包含一个整数 N。
一个整数表示答案。
1≤N≤105,
0≤Ai,Bi,Ci≤105
输入
1 1 1
2 2 2
3 3 3
输出(二分查找) O(nlogn)
IA = lambda:map(int, input().split())
n = int(input())
a = list(IA())
b = list(IA())
c = list(IA())
a.sort()
c.sort()
def get_min(x):
l = 0
r = n-1
while l < r:
# print(l, r)
mid = (l + r + 1 ) >> 1
if a[mid] >= x:
r = mid - 1
else:
l = mid
if a[l] < x:
return l + 1
else:
return 0
def get_max(x):
l = 0
r = n-1
while l < r:
mid = (l + r ) >> 1
if c[mid] <= x:
l = mid +1
else:
r = mid
if c[l] > x:
return len(c) - l
else:
return 0
res = 0
for i in range(n):
n1 = get_min(b[i])
n2 = get_max(b[i])
res += n1 * n2
print(res)
前缀和(0(nlog(n)))
#include
双指针
IA = lambda:map(int, input().split())
n = int(input())
a = list(IA())
b = list(IA())
c = list(IA())
a.sort()
c.sort()
b.sort()
res = 0
n1 = 0
n2 = 0
l1 = 0
l2 = 0
for i in range(n):
while l1 < n and a[l1] < b[i]:
n1 += 1
l1 += 1
while l2 < n and c[l2] <= b[i]:
n2 += 1
l2 += 1
res += n1 * (n - n2)
print(res)