首页 > 其他分享 >[LOJ 6029]「雅礼集训 2017 Day1」市场 题解

[LOJ 6029]「雅礼集训 2017 Day1」市场 题解

时间:2023-07-03 21:45:01浏览次数:47  
标签:lfloor frac LOJ 题解 LL rfloor 雅礼 取整 区间

这道题恶心之处在于区间向下取整。

这里给出两种思路:

区间覆盖做法

如果最大值和最小值向下取整后相等,则对此区间进行区间覆盖。

我考场写的是这个,但是码错了,加上习惯不好,\(100\to64\),再加上烦了弱智错误,\(64\to9\),不给出代码。

差值相等做法

注意到相邻两数的向下取整的差值不可能大于 \(1\),也就是:

\[\lfloor \frac x k\rfloor-\lfloor \frac {x-1} k\rfloor \leq 1 \]

稍微推广一下,我们得到:

\[x-1-\lfloor \frac {x-1} k\rfloor \leq x-\lfloor \frac x k\rfloor \]

这说明从整点来看,函数\(f(x)=x-\lfloor \frac x k\rfloor\) 具有单调上升的特点。

如果区间内\(f(\max)=f(\min)\),那么区间内所需要减去的差值必定相等,之间减去即可。

考虑到向下取整在进行多次后必然使数值、区间差值趋于 \(0\),因此时间复杂度维持在 \(O(n\log n)\)左右,可参考犇犇给出势能分析法。

#include <bits/stdc++.h>
#define LL long long
using namespace std;
const LL N = 1e5 + 5;
const LL inf = 1e18;
LL n, m, a[N], op, l, r, d;
struct node {
    LL l, r, len, mn, mx, sum, lz;
} t[N * 25];
LL fl(LL x, LL y) {
    if (0 <= x)
        return x / y;
    return -((-x + y - 1) / y);
}
void add(LL pos, LL k) {
    t[pos].lz += k;
    t[pos].sum += k * t[pos].len;
    t[pos].mn += k, t[pos].mx += k;
}
void pushup(LL pos) {
    t[pos].mn = min(t[pos * 2].mn, t[pos * 2 + 1].mn);
    t[pos].mx = max(t[pos * 2].mx, t[pos * 2 + 1].mx);
    t[pos].sum = t[pos * 2].sum + t[pos * 2 + 1].sum;
}
void down(LL pos) {
    if (t[pos].lz != 0) {
        LL k = t[pos].lz, l = pos * 2, r = pos * 2 + 1;
        add(l, k), add(r, k);
        t[pos].lz = 0;
    }
}
void build(LL pos, LL l, LL r) {
    t[pos].l = l, t[pos].r = r, t[pos].len = (r - l + 1);
    if (l == r) {
        t[pos].mx = t[pos].mn = t[pos].sum = a[l];
        return;
    }
    LL mid = (l + r) / 2;
    build(pos * 2, l, mid), build(pos * 2 + 1, mid + 1, r);
    pushup(pos);
}
void upd1(LL pos, LL l, LL r, LL k) {
    if (t[pos].r < l || r < t[pos].l)
        return;
    if (l <= t[pos].l && t[pos].r <= r) {
        add(pos, k);
        return;
    }
    down(pos);
    upd1(pos * 2, l, r, k), upd1(pos * 2 + 1, l, r, k);
    pushup(pos);
}
void upd2(LL pos, LL l, LL r, LL k) {
    if (t[pos].r < l || r < t[pos].l)
        return;
    if (l <= t[pos].l && t[pos].r <= r && t[pos].l == t[pos].r) {
        t[pos].mn = t[pos].mx = t[pos].sum = fl(t[pos].sum, k);
        return;
    }
    down(pos);
    if (l <= t[pos].l && t[pos].r <= r && t[pos].mn - fl(t[pos].mn, k) == t[pos].mx - fl(t[pos].mx, k)) {
        add(pos, fl(t[pos].mx, k) - t[pos].mx);
        return;
    }
    upd2(pos * 2, l, r, k), upd2(pos * 2 + 1, l, r, k);
    pushup(pos);
}
LL querymn(LL pos, LL l, LL r) {
    if (t[pos].r < l || r < t[pos].l)
        return inf;
    if (l <= t[pos].l && t[pos].r <= r)
        return t[pos].mn;
    down(pos);
    return min(querymn(pos * 2, l, r), querymn(pos * 2 + 1, l, r));
}
LL querysum(LL pos, LL l, LL r) {
    if (t[pos].r < l || r < t[pos].l)
        return 0;
    if (l <= t[pos].l && t[pos].r <= r)
        return t[pos].sum;
    down(pos);
    return querysum(pos * 2, l, r) + querysum(pos * 2 + 1, l, r);
}
int main() {
    scanf("%lld%lld", &n, &m);
    for (int i = 1; i <= n; i++) {
        scanf("%lld", &a[i]);
    }
    build(1, 1, n);
    for (int i = 1; i <= m; i++) {
        scanf("%lld", &op);
        if (op == 1) {
            scanf("%lld%lld%lld", &l, &r, &d);
            l++, r++;
            upd1(1, l, r, d);
        }
        if (op == 2) {
            scanf("%lld%lld%lld", &l, &r, &d);
            l++, r++;
            upd2(1, l, r, d);
        }
        if (op == 3) {
            scanf("%lld%lld", &l, &r);
            l++, r++;
            printf("%lld\n", querymn(1, l, r));
        }
        if (op == 4) {
            scanf("%lld%lld", &l, &r);
            l++, r++;
            printf("%lld\n", querysum(1, l, r));
        }
    }
    return 0;
}

标签:lfloor,frac,LOJ,题解,LL,rfloor,雅礼,取整,区间
From: https://www.cnblogs.com/dengduck/p/17524182.html

相关文章

  • [LOJ 6030]「雅礼集训 2017 Day1」矩阵 题解
    首先不难想到一个贪心,就是先填出一个全黑的行,然后再用其填黑列。而且在其中“填出一个全黑的行步数”我们应该最小化。这个贪心的正确性证明如下:必要性:填黑列的必要条件为有一个全黑的行。充分性:“填黑列的步数”就是“非全黑列的数量”。显然,如果填出一个全黑的行的过程中......
  • Property ‘sqlSessionFactory‘ or ‘sqlSessionTemplate‘ are required 问题解决
    以下是报错日志解决方案确认以下配置是否都存在:1、配置文件有写mybatis配置2、启动类里加上Mapper扫描的注解(指向自己mapper存放的位置)3、删除SpringBootApplication注解的exclude属性:@SpringBootApplication(exclude={DataSourceAutoConfiguration.class,DataSourc......
  • P2202 题解
    前言题目传送门!更好的阅读体验?提供一个平衡树做法,虽然和std::set一个道理就是了。(那你为啥不写set!!!!)前置知识如何判断两个点对应的正方形相交?正方形的边长是\(k\),中心距离四条边就是\(\dfrack2\)了。中心要相隔严格小于两段\(\dfrack2\),显然只需满足:\[|X_p-X_q|,|Y_......
  • 【CF1621G】Weighted Increasing Subsequences 题解(优化树状数组)
    CF传送门|LG传送门。优化树状数组+反向处理。Solution发现直接做不好下手。难点主要在求出所有的上升子序列并计算它们分别的贡献。所以需要反向考虑每个单点在什么情况下产生贡献。一个单点会产生多少贡献。一个单点产生贡献的条件很容易得到。一个是在一个上升子序......
  • 题解 ARC163C【Harmonic Mean】
    没想出来什么优美的解法,来个乱搞。特判平凡情况\(n\le2\),其中\(n=1\)显然有\(1=\frac{1}{1}\),\(n=2\)无解。众所周知\(1=\frac{1}{2}+\frac{1}{4}+\frac{1}{8}+\cdots+\frac{1}{2^k}+\frac{1}{2^k}\)。注意到公式中除了\(\frac{1}{2^k}\)有重复外,其余项均无重复。容易......
  • AtCoder ABC307D 题解
    AtCoderABC307DMismatchedParentheses题解思路分析First——配对括号序列首先,每个右括号肯定是要与其左边最近的左括号配对。因此,我们便可以使用一个栈来进行存放左括号的下标。当有右括号时,便可以弹出栈顶元素,但是栈为空时,便无法配对。拿样例1举个例子:8a(b(d))c......
  • 洛谷 P1081 题解
    P1081[NOIP2012提高组]开车旅行题解Link洛谷题目链接Solution首先考虑这道题的暴力做法,对于第一问,枚举每个起始点,暴力计算每个点之后最近和第二近的位置,计算答案,最后取最大值。对于第二问,对每个询问独立模拟即可。复杂度较高,无法通过此题。第一个优化:考虑到对于固定的当......
  • docker启动RabbitMQ以及常见问题解决
    docker启动MQ容器下载docker镜像dockersearchrabbitmqdockerpullrabbitmqdockerrun-d--hostnamemy-rabbit--namerabbit-p15672:15672-p5672:5672rabbitmq:latest启动容器后浏览器无法访问dockerexec-it3b124f0c9712/bin/bashrabbitmq-pluginsenab......
  • CF842E Nikita and game 题解
    题意一棵树初始只有一个编号为1的根结点。\(n\)次操作,每次新增一个点作为\(p_i\)的子结点,询问更新后有多少点可以作为树直径的端点。\(n\le3\times10^5\)。题解以下\(dist(x,y)\)表示点\(x\)与点\(y\)在树上的距离。不难发现若干条直径必然叠合于至少一点,任选这......
  • Codeforces Round 881 Div2 A-F1题解
    codeforcesround881div2题解马上要秋招了,自己本事全丢了,感觉如果这样的话今年就估计要饿死了。先打div3,7月份得开始收心了A.SashaandArrayColoring题意,可以分任意组,每组的贡献是max-min,问最大贡献显然是贪心,从大到小配对一下就行,不想放代码了’B.LongLong给出一......