敦敦敦的数据结构题!(

集训(一)

2017.11.25 ~ 2017.12.07
一息尚在,安敢回头

好题标粗辣!

// 一段话之前有 ‘TAT’ 的是直接粘的 PPT 上的,下面 ‘’ 中会有写自己的解释

// 如果网上找不到的题或者是很难找到的题会放上题意,否则会给出题号

11.28

下午敦敦敦来讲数据结构!感觉很多题都很不可做啊
(准备好好看一看课件 qwq
// 敦敦敦的题都十分巧妙啊!都是好题呀!

  • 序列

    题意:给定一个长度为 n 的序列 a[1 .. n],定义 f(l, r) = a[l .. r] 中的最小值
    有 Q 次询问,每次给出 l, r,求 lijrf(i,j)
    1n,Q105,0|ai|106

    TAT (全局
    先考虑当区间是 [1, n] 时怎么做
    这是个经典题
    cl[i] 为最大的 j 满足 a[j] ≤ a[i],若不存在则为 0
    cr[i] 为最小的 j 满足 a[j] < a[i],若不存在则设为右边界 + 1(即 n + 1
    答案就是 ni=1a[i](icl[i])(cr[i]i)
    (必须满足 cl[i] ≤ i < cr[i]

    (我们找到 cl[i]cr[i] 以后,那么在 cl[i] ~ cr[i] 这个区间中的最小值就是 a[i],所以每个 i 的贡献都是 a[i](icl[i])(cr[i]i) ,求个和即可。
    (还要注意 cl[i] ~ ii ~ cr[i] 这两个区间内,必须是有一个取到等号,一个不取等号,否则会算重。
    什么不理解?那我们模拟一下好了 …

    1 2 2
    
    cl[1]=0 cr[1]=4
    cl[2]=1 cr[2]=4
    cl[3]=2 cr[3]=4
    ans = 1 * 1 * 3   +   2 * 1 * 2   +   2 * 1 * 1  = 9; // 左区间取到等号,右区间没取到
    
    cl[1]=0 cr[1]=4
    cl[2]=1 cr[2]=4
    cl[3]=1 cr[3]=4
    ans = 1 * 1 * 3   +   2 * 1 * 2   +   3 * 2 * 1  = 11; // 都取到了等号
    

    TAT (区间询问
    接下来考虑区间询问
    显然就算取的是一个区间,cl[i]cr[i] 也是不变的,顶多会超出边界
    对答案的贡献是 a[i](imax(l1,cl[i]))(min(r+1,cr[i])i)

    TAT (分类讨论
    l >= cl[i] + 1, r <= cr[i] - 1 时,贡献系数是 (ri)(il)=rl+(r+l)ii2
    以此类推,最后可以发现,对于一个区间 (l,r) 他的答案可以表示成 k1(rl)+k2r+k3l+k4
    考虑离线,从左往右枚举 rr 固定时 i 的贡献只有两种,分别针对 l ∈ [1, cl[i] + 1]l ∈ [c[i] + 2, n],分段加一下,
    然后当 r 到了某个值后有些 i 的贡献还会改变
    用线段树维护那个四元组,时间复杂度: O((n+Q)logn)

  • segment tree

    题意:给定 n,定义 f(l, r) 为在线段树上对 (l, r) 进行区间求和需要经过的结点的个数
    有 Q 次询问,每次询问 LlrRf(l,r)
    1n,Q105

    TAT (做法
    访问到这个结点等价于包含这个结点的区间但不包含父亲的区间
    用线段树维护即可
    时间复杂度: O((n+Q)logn)

  • 【Wannafly 挑战赛 2】D - Delete 题解(这道题的题解在最后

    题意:给定一个 n 个点,m 条边的带权有向无环图,同时给定起点 S 和终点 T
    一共有 Q 个询问,每次询问删掉某个点和所有与这个点相连的边之后 ST 的最短路的长度,
    询问之间互相独立(也就是删除操作在询问结束之后会立即撤销)
    1n,q105 1m2105 ,边权的绝对值 109

    (我们首先要注意一个看上去没有那么有用的信息 … 恩它是一个有向无环图 … 所以我们要想到拓扑序
    TAT (拓扑序
    这题有个特点,就是它是一个有向无环图,那么我们可以对他求拓扑序
    可以发现对于一条路径,它经过的点的拓扑序一定是单调增加的
    当我们删除了某个点 x 后,相当于在拓扑序中删除了这个点,然后求最短路

    (因为拓扑序,所以删除一个点 u 后,一定有边 u 的左边连到 u 的右边,枚举所有这样的边 (x, y, w),用 dist(S, x) + w + dist(y, T) 更新拓扑序中区间 (x, y) 的最小值。

    查询用线段树维护即可。时间复杂度: O(nlogn+Q)

  • 【BZOJ 3306】树 题解

    dfs 序对应的区间就是子树,这样就能用线段树维护。

    如果没有换根的话,就是用线段树维护 dfs 序,然后单点修改,区间询问。

    有换根其实就是在没有换根的基础上分类讨论一下就好。
    我们进行换根操作就是直接让 root 等于要换的那个节点。最开始的时候树以 1 为根。
    分类讨论具体请看上面那个题解 ↑。

    这里说一下当 lca(x, root) = x 时,这时从以 1 为根的树中看,rootx 子树内。找到 xroot 路径中最接近 x 的结点 y,然后查询的时候踢开以 y 为根的子树范围查询。
    为什么?
    因为你换根是直接赋的值啊 … 这样做正确性显然辣。

  • 【BZOJ 4383】 【POI 2015】Pustynia 题解

    建一张拓扑图,如果 x必须比 y 大,则 xy 连边,最后如果有环则无解,否则任意求个拓扑序就是答案。这样做边数是 O(N2) 的,考虑优化建图。

    接下来有一个套路:用数据结构优化建图。

    对于每条信息,我们新建一个虚拟结点 now
    对于 [l, r] 中所有给出的较大的位置 x[i]now->x[i] 边权为 0
    所有 [l, r] 中除 x 以外的位置 y[i],利用线段树优化建图,x[i] 把区间 [l, r] 分成了好几段,每次连边的时候直接让线段树中对应的区间 (l1, r1) 连向 now,边权为 1
    也就是 (l1,r1)1>now0>x[i]
    总边数 O(n+klogn)

    因为很多点已经给出了权值,那么 f[i] 应该对 a[i]max,如果 f[x] > a[x],无解。
    如果有某个点的权值超过 109 ,无解。
    如果图中存在环,无解。

  • and

    题意:给定一个序列 a[1..n]Q 次操作,操作有三种:
    C l r x:将 a[l..r] 全部改为 x
    S l r:求 ri=la[i]
    A l r x:令 a[l..r] 中每个数都 andx
    1n,Q105 0a[i],x109

    TAT(问题转化
    首先,根据位运算的独立性,可以位与位之间分别维护,这样就花费了 O(loga[i]) 的代价使得 x 变成了 01

    (就是建三十个线段树 … 按位建,每一位分开来处理
    为什么(至少)是三十个线段树?
    因为 0a[i],x109 109 的二进制位有三十位。

    TAT(问题转化
    于是 C 操作就是区间覆盖
    S 就是区间求和
    A 操作:若 x = 1 则啥都不干,否则也是区间覆盖
    区间覆盖区间求和可以直接线段树维护,时间复杂度: O((N+Q)log2n)

  • 【UOJ 164】【清华集训 2015】V 题解

    对于修改操作,我们打标记 (a, b),代表对于该点维护的区间,执行这个标记,对于区间内的数,都要先加上 a 然后与 bmax。那么对于操作 1、2、3,分别对应 (x, - inf),(- x, 0),(- inf, x)

    考虑标记如何下传,显然这个标记是可以下传的,即 (a + A, max(b + A, B))

    对于询问单点历史最值,要注意我们需要记录的是历史最大标记而不是直接在每个点记录历史最大值。
    为什么?
    因为假设我们进行一次区间赋为 inf 的操作,接着又全部赋为 0,标记还没来得及下传更新历史最大值就被后一个标记覆盖了,所以每个点记录历史最大值是错的。

  • ball

    题意:有一个正整数序列 a[1..n]m 个区间 [l, r]
    有 Q 次操作,每次让 a[x] −= y,保证每时每刻 a[x] >= 0
    每次操作过后,你需要回答初始给定的 m 个区间里,有几个满足区间和为 0
    1n,m,q105

    TAT (做法
    a[1..n] 建线段树,于是每个区间可以看成线段树上 O(logn) 个结点
    一个区间的和为 0 等价于这 O(logn) 个结点的和都为 0
    每次单点修改后如果有新的结点和变成 0 了就暴力枚举下包含这个结点的区间
    时间复杂度: O((n+Q+m)logn)

  • 【BZOJ 3702 / 2212】【Poi 2011】Tree Rotations 题解

    权值线段树和区间线段树的唯一区别就是叶子节点的存储信息,区间所维护的信息。

    子树 x 内的逆序对个数为 :x 左子树内的逆序对个数 + x 右子树内的逆序对个数 + 跨越 x 左子树与右子树的逆序对。

    左右子树内部的逆序对与是否交换左右子树无关,因为子树内的顺序对子树之间的贡献是没有影响的。是否交换左右子树取决于交换后 “跨越 x 左子树与右子树的逆序对” 是否会减小。

    因此我们要求出是否交换这两种情况下跨越 x 左子树与右子树的逆序对,对每个叶子节点建一个权值线段树,对每个非叶子节点合并他的两个儿子节点的权值线段树,合并的时候算出逆序对数,用其中较小的一个更新答案。而不需要真正的去交换子树。
    时间复杂度: O(nlogn)

  • 【BZOJ 4408】【Fjoi 2016】神秘数 题解

    如果存在一个集合,使得 [1, x - 1] 内的数字都能被表示,此时神秘数为 x 新加入一个数 y,那么会出现如下两种情况:
      1. y ≤ x,则新集合可以表示 [1, x - 1 + y] 内的所有数字。
      2. y > x,则新集合表示的区间会产生“断裂”,即 x 依旧无法被表示,所以该集合的神秘数还是 x

    基于以上分析,产生下面的算法,用以求一个给定集合的神秘数:
    首先设 ans = 1,作为最初的神秘数,然后求出 aiansai
    那么如果 get < ans,则 ans 就是神秘数,否则令 ans = get + 1,继续过程。

  • 【CC DGCD】Dynamic Gcd

    题意:给定一棵 n 个结点的带点权的树,有 Q 次操作:
    (1)询问两点 lr 之间路径上所有结点点权值的最大公约数。
    (2)给两点 lr 之间路径上所有点的权值加上一个值 val
    1n,Q50000

    TAT (转化
    利用树链剖分 + dfs 序,可以将询问转化为求 O(logn) 个区间的 gcd,修改也转化为对 O(logn) 个区间进行区间加
    根据 辗转相减法gcd(a[1], a[2] ... a[k]) = gcd(a[l], a[2] − a[1], ... a[k] − a[k − 1])
    定义一个差分数组 c[i] = a[i] − a[i − 1]
    那么 gcd(a[1], a[2] ... a[k]) = gcd(a[1], c[2] ... c[k])
    对于区间 l ~ r 加操作,只要让 c[l] 加上 valc[r + 1] 减去 val。对于 a[1]c[k] 特判一下即可。
    线段树维护下区间 gcd 即可。
    时间复杂度: O((n+Q)log3n)

  • 方程最小值

    题意:给定 n 对整数 k[i], b[i]
    fm(x)=mi=1|kix+bi|
    fi(x) 的最小值,对每个 i1 ~ n 求一次值(x 是未给定的
    1n105,0|k|103,0|bi|109

    TAT (做法
    如果 k = 1,易得应该让 x 取的是 −b[i]中位数(可以自己举个例子
    如果 k < 0,则让 k, b 变成 −k, −b 也不影响答案,所以可以假设 k > 0
    于是 |kx + b| = k|x + b / k|,相当于有 k|x + b / k|
    用线段树维护一下中位数即可

  • 【BZOJ 4456】【Zjoi 2016】旅行者 题解

    不妨设 n <= m
    那么两点间的最短路要么跨过中线,要么两点在中线的同一侧
    对于跨过中线的情况,我们可以对中线上的每一个点求出他到其他点的最短路,然后枚举这条路径是跨过中线的哪一个点
    对于在中线的同一侧的情况,我们递归求解


    (不会证复杂度,证明

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值