首页 > 其他分享 >【题解】「KDOI-06-S」补题

【题解】「KDOI-06-S」补题

时间:2023-10-16 20:11:59浏览次数:39  
标签:le 06 题解 sum KDOI 补题 500005 ll

「KDOI-06-S」

A.「KDOI-06-S」消除序列

赛时写了一个 \(O(nq)\) 的线性 DP,喜提 60 分。

注意到如果操作 1 被使用,则一定只会使用一次,而且在最优策略中一定是第一次使用操作 1。则我们可以通过以下方式进行操作,使序列满足条件:
首先执行 \(a_i\) 和 \(\sum^{j \le i,i \in P}_{j = 1} c_j\) 使前 \(i\) 个元素符合条件,然后执行 \(\sum_{j = i + 1}^{j \le n, j \not \in P} b_i\) 使 \([i+1, n]\) 符合条件。
考虑如何计算:\(\sum_{j = i + 1}^{j \le n, j \not \in P} b_j = \sum_{j = i + 1}^{j \le n} b_i - \sum_{j = i + 1}^{j \le n, j \in P} b_j\) ,两项都可以后缀和维护,则原式 \(=\)

\[(a_i + \sum^{j \le i,i \in P}_{j = 1} c_j) + (\sum_{j = i + 1}^{j \le n} b_j - \sum_{j = i + 1}^{j \le n, j \in P} b_j) \\ = (a_i + \sum_{j = i + 1}^{j \le n} b_j) + (\sum^{j \le i,i \in P}_{j = 1} c_j - \sum_{j = i + 1}^{j \le n, j \in P} b_j) \]

后两项对于同一段 \([p_i,p_{i+1})\) 相同,前两项最小值可以 ST 表或者线段树维护。所以可以枚举每一段,每次做到每次询问复杂度为 \(O(m)\) 或者 \(O(m \log n)\),足以通过本题。
容易证明最优解的操作一定符合这种方式,因为这种方式没有重复操作。
参考代码(code by @westernhan):

#include <cstdio>
#include <cstdlib>
#include <algorithm>
using namespace std;
typedef long long ll;
const ll inf = 1e18;
int n, m, q, a[500005], b[500005], c[500005], p[500005];
ll sumb[500005], sumc[500005], num[500005];
class ST
{
public:
    ll t[500005][35];
    ll logg(ll w)
    {
        ll res = -1;
        while (w)
            w >>= 1, res++;
        return res;
    }
    void init(void)
    {
        for (int i = 0; i <= n; i++)
            t[i][0] = sumb[i + 1] + a[i];
        for (int i = 1; i <= 25; i++)
            for (int j = 0; j + (1 << (i - 1)) <= n; j++)
                t[j][i] = min(t[j][i - 1], t[j + (1 << (i - 1))][i - 1]);
    }
    ll query(int l, int r)
    {
        if (l > r)
            return inf;
        int len = logg(r - l + 1);
        return min(t[l][len], t[r - (1 << len) + 1][len]);
    }
} T;
int main(void)
{
    scanf("%d", &n);
    for (int i = 1; i <= n; i++)
        scanf("%d", a + i); // copy 0
    for (int i = 1; i <= n; i++)
        scanf("%d", b + i); // set 0
    for (int i = n; i >= 1; i--)
        sumb[i] = sumb[i + 1] + b[i];
    for (int i = 1; i <= n; i++)
        scanf("%d", c + i); // set 1
    T.init();
    scanf("%d", &q);
    while (q--)
    {
        ll maxn = inf;
        scanf("%d", &m);
        for (int i = 1; i <= m; i++)
        {
            scanf("%d", p + i);
            sumc[i] = sumc[i - 1] + c[p[i]];
            num[i] = num[i - 1] + b[p[i]];
        }
        for (int i = 1; i <= m; i++)
        {
            ll res = 0;
            res += T.query(p[i - 1], p[i] - 1);
            res -= num[m] - num[i - 1];
            res += sumc[i - 1];
            maxn = min(maxn, res);
        }
        ll res = 0;
        res += T.query(p[m], n);
        res += sumc[m];
        maxn = min(res, maxn);
        printf("%lld\n", maxn);
    }
    return 0;
}

标签:le,06,题解,sum,KDOI,补题,500005,ll
From: https://www.cnblogs.com/JXOIer-zaochen/p/17768239.html

相关文章

  • [COCI2015-2016#4] ENDOR 题解
    [COCI2015-2016#4]ENDOR题解首先要发现一个很重要的性质,那就是两只变色龙碰撞后回头,等效于两只变色龙继续往前走,其中向右走的颜色不变,而向左走的要改变颜色。那这样就有一种\(O(n^2)\)的做法:对于向右的变色龙,直接贡献答案;对于向左的变色龙,我们按照碰到的先后顺序枚举它前面......
  • 【题解】AtCoder-ARC167
    AtCoder-ARC167AToastsforBreakfastParty一定不会有空盘,问题转化成\(2m\)个数,其中\(2m-n\)个是\(0\),这样一定是最大值和最小值一起,次大值和次小值一起,以此类推。提交记录:Submission-AtCoderAtCoder-ARC167BProductofDivisors\(A^B=\prod_ip_i^{Bc_i}\),那么答案......
  • CF1119F Niyaz and Small Degrees 题解
    原题翻译首先\(O(n^2\logn)\)的dp是simple的,我们设\(dp_{i,0/1}\)表示以\(i\)为根,\(i\)到\(fa_i\)这条边删/不删的最小权值和。转移是一个非常trick的问题,只需要假设所有都选\(dp_{i,0}\),然后把所有儿子按照\(dp_{v,1}+w(u,v)-dp_{v,0}\)排序,选前\(d......
  • P9745 「KDOI-06-S」树上异或 题解
    P9745「KDOI-06-S」树上异或题解\(x_i=0\)这题一看就不是很可做,先考虑部分分。对于一条链的情况,我们可以枚举上一个断边的位置,然后转移。一看数据范围,估计和值域有关,所以考虑\(x_i=1\)的部分分,如果全部点权都是1,那么一种方案只有0和1两种取值,考虑这个状态设计:\(f......
  • [ARC167D] Good Permutation 题解
    题意对于一个长度为\(N\)的排列\(Q\),定义其为好的,当且仅当对于任意整数\(i\in\left[1,N\right]\),在进行若干次操作\(i\leftarrowQ_i\)后可以得到\(i=1\)。给定一个排列\(P\),定义一次操作为交换两个数。定义\(M\)为可以将\(P\)变为一个好的的排列的最小操......
  • 计算机网络的分组转发算法例题解析
    例题展示例题解决将题目中要求的ip地址与相对应的子网掩码进行二进制上面的相与即可,若是与目的ip地址一致,那么就直接跳转到其对应的那个接口;否则就直接跳转到默认接口;本题答案为R2;......
  • Gym101064L The Knapsack problem
    CF传送门发现物品的体积很小,尝试从此处入手。设\(K\)为最大的物品体积。把背包体积\(m\)分成差不超过\(K\)的两部分,然后合并。这样需要求出\(f(\frac{m}{2}-K\sim\frac{m}{2}+K)\)。递归地,可以发现需要求出\(f(\frac{m}{2^k}-K\sim\frac{m}{2^k}+K)\)。最......
  • UVA1366 Martian Mining 题解
    这个题可以用动态规划解决。令\(sbe_{i,j}\)为第\(j\)列\(1\)至\(i\)个格子\(BE\)矿总和,令\(snw_{i,j}\)为第\(i\)行\(1\)至\(j\)个格子\(NEW\)矿总和。\(dp_{i,j,0}\)表示为以第(\(i\),\(j\))为右下角,第(\(i\),\(j\))号格子建立\(BE\)矿管道的最大采矿量。\(dp......
  • P8854 [POI2002] 超级马 题解
    这题其实就是搜索,不知道怎么评绿的。题意有一个大小无限的棋盘,有一只马,给定\(n\)种跳法,判断马是否能跳到棋盘所有点。题解搜索马是否可以跳到他上下左右的四个点,因为只要能跳到这四个点,就可以以这四个点为基础跳到其他所有的点。这里有一些细节需要处理:因为每次操作能是......
  • CF1873E Building an Aquarium 题解
    这题看到第一眼就是二分。单调性二分最关键的东西是单调性在哪。单调性是如果高度越高,需要的水就越多,高度越矮,要用的水越少。不难得出代码:check函数:intcheck(intmid){ intsum=0; for(inti=1;i<=n;i++){ sum+=max(0ll,mid-a[i]); } if(sum<=x)returnsum; elsere......