题目描述

给出一个长度为 $n$ 的序列,支持 $m$ 次操作,操作有四种:区间加、区间下取整除、区间求最小值、区间求和。

$n\le 100000$ ,每次加的数在 $[-10^4,10^4]$ 之间,每次除的数在 $[2,10^9]$ 之间。


题解

线段树+均摊分析

和 【uoj#228】基础数据结构练习题 类似的均摊分析题。

对于原来的两个数 $a$ 和 $b$ ( $a>b$ ) ,原来的差是 $a-b$ ,都除以 $d$ 后的差是 $\frac{a-b}d$ ,相当于差也除了 $d$ 。

而当区间差为 $0$ 或 $a=kd,b=kd-1$ 的 $1$ 时,区间下取整除就变成了区间减。

因此当一个区间下取整除了 $\log(Max-Min)$ 次后就不需要暴力下取整除,直接区间减即可。

定义线段树节点势能为 $\log(Max-Min)$ ,那么每次对 $[l,r]$ 下取整除就是将所有 $l\le x,y\le r$ ,且势能不为 $0$ 的节点 $[x,y]$ 的势能减 $1$ ,代价为势能减少总量。

分析区间加操作:只会修改到经过的节点的势能,影响 $\log$ 个节点,将这些点的势能恢复为 $\log(Max-Min)$ 。

因此总的时间复杂度就是总势能量 $O((n+m\log n)\log a)$ 。

注意C++中的 '/' 并不是下取整,而是向0取整,因此需要按正负分类讨论手写下取整。

#include <cstdio>
#include <algorithm>
#define N 400010
#define lson l , mid , x << 1
#define rson mid + 1 , r , x << 1 | 1
using namespace std;
typedef long long ll;
ll sum[N] , mx[N] , mn[N] , add[N];
inline ll fdiv(ll x , ll y)
{return x > 0 ? x / y : (x - y + 1) / y;
}
inline void pushup(int x)
{sum[x] = sum[x << 1] + sum[x << 1 | 1];mx[x] = max(mx[x << 1] , mx[x << 1 | 1]);mn[x] = min(mn[x << 1] , mn[x << 1 | 1]);
}
inline void pushdown(int l , int r , int x)
{if(add[x]){int mid = (l + r) >> 1;sum[x << 1] += add[x] * (mid - l + 1) , sum[x << 1 | 1] += add[x] * (r - mid);mx[x << 1] += add[x] , mx[x << 1 | 1] += add[x];mn[x << 1] += add[x] , mn[x << 1 | 1] += add[x];add[x << 1] += add[x] , add[x << 1 | 1] += add[x];add[x] = 0;}
}
void build(int l , int r , int x)
{if(l == r){scanf("%lld" , &sum[x]) , mx[x] = mn[x] = sum[x];return;}int mid = (l + r) >> 1;build(lson) , build(rson);pushup(x);
}
void vadd(int b , int e , ll a , int l , int r , int x)
{if(b <= l && r <= e){sum[x] += a * (r - l + 1) , mx[x] += a , mn[x] += a , add[x] += a;return;}pushdown(l , r , x);int mid = (l + r) >> 1;if(b <= mid) vadd(b , e , a , lson);if(e > mid) vadd(b , e , a , rson);pushup(x);
}
void vdiv(int b , int e , ll d , int l , int r , int x)
{if(b <= l && r <= e && mx[x] - fdiv(mx[x] , d) == mn[x] - fdiv(mn[x] , d)){ll a = mx[x] - fdiv(mx[x] , d);sum[x] -= a * (r - l + 1) , mx[x] -= a , mn[x] -= a , add[x] -= a;return;}pushdown(l , r , x);int mid = (l + r) >> 1;if(b <= mid) vdiv(b , e , d , lson);if(e > mid) vdiv(b , e , d , rson);pushup(x);
}
ll qmin(int b , int e , int l , int r , int x)
{if(b <= l && r <= e) return mn[x];pushdown(l , r , x);int mid = (l + r) >> 1;ll ans = 1ll << 62;if(b <= mid) ans = min(ans , qmin(b , e , lson));if(e > mid) ans = min(ans , qmin(b , e , rson));return ans;
}
ll qsum(int b , int e , int l , int r , int x)
{if(b <= l && r <= e) return sum[x];pushdown(l , r , x);int mid = (l + r) >> 1;ll ans = 0;if(b <= mid) ans += qsum(b , e , lson);if(e > mid) ans += qsum(b , e , rson);return ans;
}
int main()
{int n , m , opt , x , y;ll z;scanf("%d%d" , &n , &m);build(1 , n , 1);while(m -- ){scanf("%d%d%d" , &opt , &x , &y) , x ++ , y ++ ;if(opt == 1) scanf("%lld" , &z) , vadd(x , y , z , 1 , n , 1);if(opt == 2) scanf("%lld" , &z) , vdiv(x , y , z , 1 , n , 1);if(opt == 3) printf("%lld\n" , qmin(x , y , 1 , n , 1));if(opt == 4) printf("%lld\n" , qsum(x , y , 1 , n , 1));}return 0;
}

转载于:https://www.cnblogs.com/GXZlegend/p/8715279.html

【loj6029】「雅礼集训 2017 Day1」市场 线段树+均摊分析相关推荐

  1. ZCUM-1948: #6029. 「雅礼集训 2017 Day1」市场 线段树区间更新

    题目连接:点击打开链接 从前有一个贸易市场,在一位执政官到来之前都是非常繁荣的,自从他来了之后,发布了一系列奇怪的政令,导致贸易市场的衰落. 有 n nn 个商贩,从 0∼n−1 0 \sim n - ...

  2. 数据结构二之线段树Ⅱ——KiKi‘s K-Number,ball,The Child and Sequence,「雅礼集训 2017 Day1」市场,Atlantis

    值域线段树+势能线段树+扫描线 KiKi's K-Number ball The Child and Sequence 「雅礼集训 2017 Day1」市场 Atlantis KiKi's K-Num ...

  3. #6029. 「雅礼集训 2017 Day1」市场(势能,区间除)

    #6029. 「雅礼集训 2017 Day1」市场 用线段树维护数列,区间上维护最大最小值,区间和还有标记,修改时,区间加直接做,而区间除时,递归到线段树上某一区间,如果这一操作等价于区间加(也就是最 ...

  4. LibreOJ#6030. 「雅礼集训 2017 Day1」矩阵

    https://loj.ac/problem/6030 如果矩阵第i列有一个黑色, 那可以用他把第i行全都染黑,也可以使任意一列具有黑色 然后就可以用第i行把矩阵染黑 染黑一列的代价最少是1 染黑一行 ...

  5. [LOJ 6042]「雅礼集训 2017 Day7」跳蚤王国的宰相(树的重心+贪心)

    [LOJ 6042]「雅礼集训 2017 Day7」跳蚤王国的宰相 description solution 一个到所有节点距离和最小的节点 ⇔\Leftrightarrow⇔ 树的重心(满足最重的儿 ...

  6. #6034. 「雅礼集训 2017 Day2」线段游戏 李超树

    #6034. 「雅礼集训 2017 Day2」线段游戏 内存限制:256 MiB时间限制:1000 ms标准输入输出 题目类型:传统评测方式:Special Judge 上传者: 匿名 提交提交记录统 ...

  7. loj #6046. 「雅礼集训 2017 Day8」爷

    #6046. 「雅礼集训 2017 Day8」爷 题目描述 如果你对山口丁和 G&P 没有兴趣,可以无视题目背景,因为你估计看不懂 -- 在第 63 回战车道全国高中生大赛中,军神西住美穗带领 ...

  8. LOJ#6044. 「雅礼集训 2017 Day8」共(Prufer序列)

    题面 传送门 题解 答案就是\(S(n-k,k)\times {n-1\choose k-1}\) 其中\(S(n,m)\)表示左边\(n\)个点,右边\(m\)个点的完全二分图的生成树个数,它的值为 ...

  9. LOJ#6048. 「雅礼集训 2017 Day10」数列(线段树)

    题面 传送门 题解 我的做法似乎非常复杂啊-- 首先最长上升子序列长度就等于把它反过来再接到前面求一遍,比方说把\(2134\)变成\(43122134\),实际上变化之后的求一个最长上升子序列和方案 ...

最新文章

  1. 聚类分析案例:探究用户对物品类别的喜好细分降维
  2. VS 2008 .NET Framework 3.5 Training Kit
  3. 1.6的锁优化(适应性自旋/锁粗化/锁削除/轻量级锁/偏向锁)
  4. Qt学习(二):菜单栏、工具栏和对话框
  5. PostgreSQL csvlog 源码分析
  6. 前端学习(936):缓动动画原理
  7. 如何使用OSQP-Eigen
  8. XGBoost原理及在Python中使用XGBoost
  9. 数组常用方法:是否改变原数组
  10. mysql数据库是以表为单位存储的,创建一个以数据库名称为参数的MySQL存储过程,以列出具有特定数据库中详细信息的表。...
  11. Swift - 炫酷放射弹出按钮菜单(改造自AwesomeMenu)
  12. [源码剖析]tinyhttpd-C语言实现最简单的HTTP服务器
  13. Windows Server 2008 R2 Enterpris服务器上安装一个Moodle
  14. 算法导论第三版习题及答案
  15. 奇迹1.03H服务端开服架设文件Data文件详解
  16. 在linux目录中设置权限设置,linux下为目录和文件设置权限(示例代码)
  17. iOS开发-plist文件的常用操作
  18. 怎么用PHP实现检测网站文章是否被收录
  19. 软件工程 实践者的研究方法 第三章答案
  20. mysql聚合函数求数据总和的语句,MySQL数据库考试试题和答案

热门文章

  1. ASP.NET URL Rewrite. URL重写
  2. docker容器内安装ifconfig netstat ping vim 等测试工具的方法
  3. 有没有想过,你眼中的SQL进阶,别人看来连入门都不是?
  4. s:TextInput优化
  5. mysql -connector/j驱动下载
  6. 计算机网络技术的专业认识,计算机网络技术课程学习后的自我认识
  7. java正则表达式去除空格_去掉字符串前后所有空格的正则表达式
  8. python类的应用_如何剖析python应用程序的类方法?
  9. java实现蛇形输出,Java 输入一个正整数,按蛇形打印。
  10. java 快速从树节点找到数据_14期每日分享Java程序员分享超全哈希相关的知识