[acwing周赛复盘] 第第 107 场周赛 20230610

[acwing周赛复盘] 第第 107 场周赛 20230610

    • 总结
    • 5035. 四舍五入
      • 1. 题目描述
      • 2. 思路分析
      • 3. 代码实现
    • 5036. 二元组
      • 1. 题目描述
      • 2. 思路分析
      • 3. 代码实现
    • 5037. 区间异或
      • 1. 题目描述
      • 2. 思路分析
      • 3. 代码实现
    • 六、参考链接

总结

  • TT卡py干。
  • T1 数学
  • T2 哈希表
  • T3 20颗01线段树,RURQ
  • 在这里插入图片描述

5035. 四舍五入

链接: 5035. 四舍五入

1. 题目描述

[acwing周赛复盘] 第第 107 场周赛 20230610_第1张图片

2. 思路分析

  • 取余看看最后一位和5的关系。

3. 代码实现

# Problem: 四舍五入
# Contest: AcWing
# URL: https://www.acwing.com/problem/content/5038/
# Memory Limit: 256 MB
# Time Limit: 1000 ms

import sys
import random
from types import GeneratorType
import bisect
import io, os
from bisect import *
from collections import *
from contextlib import redirect_stdout
from itertools import *
from array import *
from functools import lru_cache, reduce
from heapq import *
from math import sqrt, gcd, inf

if sys.version >= '3.8':  # ACW没有comb
    from math import comb

RI = lambda: map(int, sys.stdin.buffer.readline().split())
RS = lambda: map(bytes.decode, sys.stdin.buffer.readline().strip().split())
RILST = lambda: list(RI())
DEBUG = lambda *x: sys.stderr.write(f'{str(x)}\n')
# print = lambda d: sys.stdout.write(str(d) + "\n")  # 打开可以快写,但是无法使用print(*ans,sep=' ')这种语法,需要print(' '.join(map(str, p))),确实会快。

DIRS = [(0, 1), (1, 0), (0, -1), (-1, 0)]  # 右下左上
DIRS8 = [(0, 1), (1, 1), (1, 0), (1, -1), (0, -1), (-1, -1), (-1, 0),
         (-1, 1)]  # →↘↓↙←↖↑↗
RANDOM = random.randrange(2 ** 62)
MOD = 10 ** 9 + 7
PROBLEM = """
"""


def lower_bound(lo: int, hi: int, key):
    """由于3.10才能用key参数,因此自己实现一个。
    :param lo: 二分的左边界(闭区间)
    :param hi: 二分的右边界(闭区间)
    :param key: key(mid)判断当前枚举的mid是否应该划分到右半部分。
    :return: 右半部分第一个位置。若不存在True则返回hi+1。
    虽然实现是开区间写法,但为了思考简单,接口以[左闭,右闭]方式放出。
    """
    lo -= 1  # 开区间(lo,hi)
    hi += 1
    while lo + 1 < hi:  # 区间不为空
        mid = (lo + hi) >> 1  # py不担心溢出,实测py自己不会优化除2,手动写右移
        if key(mid):  # is_right则右边界向里移动,目标区间剩余(lo,mid)
            hi = mid
        else:  # is_left则左边界向里移动,剩余(mid,hi)
            lo = mid
    return hi


def bootstrap(f, stack=[]):
    def wrappedfunc(*args, **kwargs):
        if stack:
            return f(*args, **kwargs)
        else:
            to = f(*args, **kwargs)
            while True:
                if type(to) is GeneratorType:
                    stack.append(to)
                    to = next(to)
                else:
                    stack.pop()
                    if not stack:
                        break
                    to = stack[-1].send(to)
            return to

    return wrappedfunc


#       ms
def solve():
    n, = RI()
    a = n % 10
    b = n // 10 * 10
    if a < 5:
        return print(b)
    print(b + 10)


if __name__ == '__main__':
    t = 0
    if t:
        t, = RI()
        for _ in range(t):
            solve()
    else:
        solve()

5036. 二元组

链接: 5036. 二元组

1. 题目描述

[acwing周赛复盘] 第第 107 场周赛 20230610_第2张图片

2. 思路分析

  • 两边都用哈希表计数组合即可。

3. 代码实现

def solve():
    n, m = RI()
    c = Counter()

    for i in range(1, n + 1):
        c[i % 5] += 1
    ans = 0
    for i in range(1, m + 1):
        ans += c[(5 - i % 5) % 5]
    print(ans)

5037. 区间异或

链接: 5037. 区间异或

1. 题目描述

[acwing周赛复盘] 第第 107 场周赛 20230610_第3张图片

2. 思路分析

cf原题:https://codeforces.com/contest/242/problem/E
声明,由于线段树常数问题,这题原题里也没有人用py过,我去偷了cpp代码交的。
  • 一开始想用一颗裸lazy线段树,记录异或值算,后来发现不满足性质:(a+b) XOR c == a XOR c+b XOR c。所以这个方法是错误的。
  • 那么,考虑拆位,对每一位,线段树统计这个区间上有几个1,被异或几次即可。
  • 需要20颗lazy的异或线段树,异或时,翻转,新1个数=区间长度-原值

  • 类似的题还有:2569. 更新数组后处理求和查询

3. 代码实现

注意,这份代码TLE

# Problem: 区间异或
# Contest: AcWing
# URL: https://www.acwing.com/problem/content/5040/
# Memory Limit: 256 MB
# Time Limit: 2000 ms

import sys

RI = lambda: map(int, sys.stdin.buffer.readline().split())
RS = lambda: map(bytes.decode, sys.stdin.buffer.readline().strip().split())
RILST = lambda: list(RI())
DEBUG = lambda *x: sys.stderr.write(f'{str(x)}\n')
print = lambda d: sys.stdout.write(
    str(d) + "\n")  # 打开可以快写,但是无法使用print(*ans,sep=' ')这种语法,需要print(' '.join(map(str, p))),确实会快。

MOD = 10 ** 9 + 7
PROBLEM = """
"""


class IntervalTree:
    def __init__(self, size, nums):
        self.size = size
        self.interval_tree = [0 for _ in range(size * 4)]
        self.lazys = [0 for _ in range(size * 4)]

        self.nums = nums
        self.build_tree(1, 1, size)

    def give_lay_to_son(self, p, l, r):
        interval_tree = self.interval_tree
        lazys = self.lazys
        if lazys[p] == 0:
            return
        mid = (l + r) // 2
        interval_tree[p * 2] = mid - l + 1 - interval_tree[p * 2]
        interval_tree[p * 2 + 1] = r - mid - 1 + 1 - interval_tree[p * 2 + 1]
        lazys[p * 2] ^= lazys[p]
        lazys[p * 2 + 1] ^= lazys[p]
        lazys[p] = 0

    def update(self, p, l, r, x, y, val):
        """
        把[x,y]区域全异或val
        """
        if y < l or r < x:
            return
        interval_tree = self.interval_tree
        lazys = self.lazys
        if x <= l and r <= y:
            interval_tree[p] = (r-l+1)-interval_tree[p]
            lazys[p] ^= val
            return
        self.give_lay_to_son(p, l, r)
        mid = (l + r) // 2
        if x <= mid:
            self.update(p * 2, l, mid, x, y, val)
        if mid < y:
            self.update(p * 2 + 1, mid + 1, r, x, y, val)
        interval_tree[p] = interval_tree[p * 2] + interval_tree[p * 2 + 1]

    def query(self, p, l, r, x, y):
        """
        查找x,y区间的和        """

        if y < l or r < x:
            return 0
        if x <= l and r <= y:
            return self.interval_tree[p]
        self.give_lay_to_son(p, l, r)
        mid = (l + r) // 2
        s = 0
        if x <= mid:
            s += self.query(p * 2, l, mid, x, y)
        if mid < y:
            s += self.query(p * 2 + 1, mid + 1, r, x, y)
        return s

    def build_tree(self, p, l, r):
        interval_tree = self.interval_tree
        nums = self.nums
        if l == r:
            interval_tree[p] = nums[l - 1]
            return
        mid = (l + r) // 2
        self.build_tree(p * 2, l, mid)
        self.build_tree(p * 2 + 1, mid + 1, r)
        interval_tree[p] = interval_tree[p * 2] + interval_tree[p * 2 + 1]


#       ms
def solve():
    n, = RI()
    a = RILST()
    tree = [IntervalTree(n, [v >> i & 1 for v in a]) for i in range(20)]
    m, = RI()
    for _ in range(m):
        t, *q = RI()
        if t == 1:
            l, r = q
            print(sum(tree[i].query(1, 1, n, l, r) << i for i in range(20)))
        else:
            l, r, x = q
            for i in range(20):
                p = x >> i & 1
                if p:
                    tree[i].update(1, 1, n, l, r, 1)


if __name__ == '__main__':
    n, = RI()
    a = RILST()
    tree = [IntervalTree(n, [v >> i & 1 for v in a]) for i in range(20)]
    m, = RI()
    for _ in range(m):
        t, *q = RI()
        if t == 1:
            l, r = q
            print(sum(tree[i].query(1, 1, n, l, r) << i for i in range(20)))
        else:
            l, r, x = q
            for i in range(20):
                p = x >> i & 1
                if p:
                    tree[i].update(1, 1, n, l, r, 1)

六、参考链接

你可能感兴趣的:(acwing周赛复盘,数学建模)