当前位置: 首页 > article >正文

G - Add and Multiply Queries

G - Add and Multiply Queries

思路

开始直接用的线段树,写完才意识到是假的

由于题目说答案不会超过 1 0 18 10^{18} 1018,所以一个询问区间内的大于2的b的个数不超过64个,这样一个区间内大于2的b的就可以把a分成不超过64个连续的区间,用树状数组维护,b大于2的位置可以用线段树二分或者set的做法来找到(64logn),在这种位置上判断+a和*b哪个选择更好即可

为了防止超时,实际上应该也超不了,用链表+set写复杂度仅为64+logn,具体做法是用链表维护b大于2的位置,查询的时候二分找到第一个b大于二的位置,后面的用链表来找

代码

#define lowbit(x) (x & -x)

int n;
vector<int> a, b;
vector<ll> tr;

void add(int d, int x) {
    for (; d <= n; d += lowbit(d))
        tr[d] += x;
}

ll get(int d) {
    ll res = 0;
    for (; d > 0; d -= lowbit(d))
        res += tr[d];
    return res;
}

ll getd(int l, int r) {
    return get(r) - get(l - 1);
}

void solve() {
    cin >> n;
    a.resize(n + 1), b.resize(n + 1);
    tr.resize(n + 1);
    for (int i = 1; i <= n; i++) {
        cin >> a[i];
        add(i, a[i]);
    }
    for (int i = 1; i <= n; i++)
        cin >> b[i];
    set<int> ds;
    vector<int> br(n + 1);
    int last = INF;
    for (int i = n; i >= 1; i--) {
        if (b[i] > 1) {
            ds.insert(i);
            br[i] = last;
            last = i;
        }
    }
    int q;
    cin >> q;
    while (q--) {
        int op, l, r;
        cin >> op >> l >> r;
        if (op == 1) {
            add(l, r - a[l]);
            a[l] = r;
        } else if (op == 2) {
            if (b[l] < 2 && r > 1) {
                auto tt = ds.lower_bound(l);
                if (tt != ds.end())
                    br[l] = *tt;
                else
                    br[l] = INF;
                if (tt != ds.begin()) {
                    br[*--tt] = l;
                }
                ds.insert(l);
            } else if (b[l] > 1 && r < 2) {
                auto tt = ds.lower_bound(l);
                auto ft = tt;
                if (tt != ds.begin())
                    br[*--tt] = br[l];
                ds.erase(ft);
            }
            b[l] = r;
        } else {
            ll v = a[l++];
            if (l > r)
                cout << v << endl;
            else {
                auto tt = ds.lower_bound(l);
                int d = (tt == ds.end() ? INF : *tt);
                while (d <= r) {
                    if (d > l) {
                        v += getd(l, d - 1);
                    }
                    v + a[d] >= v* b[d] ? (v += a[d]) : (v *= b[d]);
                    l = d + 1;
                    d = br[d];
                }
                if (l <= r) {
                    v += getd(l, r);
                }
                cout << v << endl;
            }
        }
    }
}

http://www.kler.cn/news/363585.html

相关文章:

  • 项目管理新趋势!2024年,Jira与禅道你更倾向谁?
  • docker harbor
  • 怎么在线制作拼团活动
  • WPF中的Style如何使用
  • 求助帖:ubuntu22.10 auto install user-data配置了为何还需要选择语言键盘(如何全自动)
  • SpringCloud学习记录|day6
  • C语言程序设计:现代设计方法习题笔记《chapter4》
  • Qt 实战(11)样式表 | 11.2、使用样式表
  • el-table动态新增/删除表单行及校验规则
  • 5G 现网信令参数学习(1) - MIB
  • 【openwrt-21.02】T750 openwrt 概率出现nat46_ipv4_input+0x90/0x4b4问题分析及解决方案
  • 【C++干货篇】——C/C++内存管理
  • yolov8s.pt转换成onxx再转换成rknn模型用于RK3588
  • arp代答观察
  • LeetCode:第1290题 二进制链表转整数
  • 构建物联网智能项目的框架与实践
  • 短视频去水印小程序流量主最新接口带配音功能
  • Python 学习笔记(十二)—— 网络编程
  • Ai环境安装教程
  • 【进阶OpenCV】 (17)-- Dlib库 --实现人脸检测
  • 家庭宽带的ip地址是固定的吗?宽带ip地址怎么修改‌
  • 深入理解 Webpack:现代前端开发的模块打包器
  • 二叉树习题其五【力扣】【算法学习day.12】
  • 【Flutter】页面布局:层叠布局(Stack、Positioned)
  • 实战:大数据冷热分析
  • 探索音频在线剪辑工具的奇妙世界