\(\mathcal{Description}\)

  Link.

  维护序列 \(\lang a_n\rang\),支持 \(q\) 次如下操作:

  1. 区间加法;

  2. 区间下取整除法;

  3. 区间求最小值;

  4. 区间求和。

    \(n,q\le10^5\),值域大约是 \(V=2\times10^9\)。

\(\mathcal{Solution}\)

  可以推测是势能线段树。对于线段树上的区间 \([l,r]\),想要将它 \(\div d\),维护 \(u=\min_{i=l}^r\{a_i\}\) 以及 \(v=\max_{i=l}^r\{a_i\}\),当 \(\lfloor\frac{u}{d}\rfloor-u=\lfloor\frac{v}{d}\rfloor-v\) 时直接打区间加法标记,否则递归处理。其他操作正常在线段树上进行,若不考虑各变量间的数量级关系,可证复杂度为 \(\mathcal O((n+q\log n)\log V)\)。

证明

  设线段树上区间 $[l,r]$ 有势能 $\Phi[l,r]=\log(v-u)$($v,u$ 定义如上),总势能 $\Phi=\sum\Phi[l,r]$,则:

  • 初始状态,\(\Phi[l,r]\le\mathcal O(\log V)\),\(\Phi\le\mathcal O(n\log V)\);
  • 区间加法,势能有变动的区间个数为 \(\mathcal O(\log n)\),\(\Delta\Phi[l,r]\le\mathcal O(\log V)\),故 \(\Delta\Phi=\sum\Delta\Phi[l,r]\le\mathcal O(\log n\log V)\);
  • 区间除法,设操作对象为区间 \([s,e]\),首先其有基础复杂度开销 \(\mathcal O(\log n)\),也有可能带来至多 \(\mathcal O(\log n\log V)\) 的势能增加。考虑树上一个被它完全覆盖的区间 \([l,r]\)。若在这个区间需要向下递归,则必然有 \(\Delta\Phi[l,r]\le-1\),所以 \(\Delta\Phi\propto x\),其中 \(x\) 即递归入完全覆盖区间的次数。那么本次操作的复杂度为 \(\mathcal O(\log n+x)\)。

  综上,总复杂度为 \(\mathcal O(q\log n)+\sum x\),即 \(\mathcal O(q\log n+n\log V+q\log n\log V)\),当然第一项可以忽略。 \(\square\)

\(\mathcal{Code}\)

/*~Rainybunny~*/

#include <cmath>
#include <cstdio> #define rep( i, l, r ) for ( int i = l, rep##i = r; i <= rep##i; ++i )
#define per( i, r, l ) for ( int i = r, per##i = l; i >= per##i; --i ) typedef long long LL;
#define int LL inline int rint() {
int x = 0, f = 1, s = getchar();
for ( ; s < '0' || '9' < s; s = getchar() ) f = s == '-' ? -f : f;
for ( ; '0' <= s && s <= '9'; s = getchar() ) x = x * 10 + ( s ^ '0' );
return x * f;
} template<typename Tp>
inline void wint( Tp x ) {
if ( x < 0 ) putchar( '-' ), x = -x;
if ( 9 < x ) wint( x / 10 );
putchar( x % 10 ^ '0' );
} inline int imin( const int a, const int b ) { return a < b ? a : b; }
inline int imax( const int a, const int b ) { return a < b ? b : a; } const int MAXN = 1e5, IINF = 1ll << 60;
int n, q; struct SegmentTree {
int len[MAXN << 2], mx[MAXN << 2], mn[MAXN << 2], adt[MAXN << 2];
LL sum[MAXN << 2]; inline void pushup( const int u ) {
mx[u] = imax( mx[u << 1], mx[u << 1 | 1] );
mn[u] = imin( mn[u << 1], mn[u << 1 | 1] );
sum[u] = sum[u << 1] + sum[u << 1 | 1];
} inline void pushad( const int u, const int v ) {
adt[u] += v, mn[u] += v, mx[u] += v, sum[u] += 1ll * v * len[u];
} inline void pushdn( const int u ) {
if ( adt[u] ) {
pushad( u << 1, adt[u] ), pushad( u << 1 | 1, adt[u] );
adt[u] = 0;
}
} inline void build( const int u, const int l, const int r ) {
len[u] = r - l + 1;
if ( l == r ) return void( mx[u] = mn[u] = sum[u] = rint() );
int mid = l + r >> 1;
build( u << 1, l, mid ), build( u << 1 | 1, mid + 1, r );
pushup( u );
} inline void add( const int u, const int l, const int r,
const int al, const int ar, const int v ) {
if ( al <= l && r <= ar ) return pushad( u, v );
int mid = l + r >> 1; pushdn( u );
if ( al <= mid ) add( u << 1, l, mid, al, ar, v );
if ( mid < ar ) add( u << 1 | 1, mid + 1, r, al, ar, v );
pushup( u );
} inline void div( const int u, const int l, const int r,
const int dl, const int dr, const int v ) {
// if ( v == 1 ) return ;
if ( dl <= l && r <= dr && mx[u] - floor( 1. * mx[u] / v )
== mn[u] - floor( 1. * mn[u] / v ) ) {
return pushad( u, floor( 1. * mx[u] / v ) - mx[u] );
}
int mid = l + r >> 1; pushdn( u );
if ( dl <= mid ) div( u << 1, l, mid, dl, dr, v );
if ( mid < dr ) div( u << 1 | 1, mid + 1, r, dl, dr, v );
pushup( u );
} inline int qmin( const int u, const int l, const int r,
const int ql, const int qr ) {
if ( ql <= l && r <= qr ) return mn[u];
int mid = l + r >> 1, ret = IINF; pushdn( u );
if ( ql <= mid ) ret = imin( ret, qmin( u << 1, l, mid, ql, qr ) );
if ( mid < qr )
ret = imin( ret, qmin( u << 1 | 1, mid + 1, r, ql, qr ) );
return ret;
} inline LL qsum( const int u, const int l, const int r,
const int ql, const int qr ) {
if ( ql <= l && r <= qr ) return sum[u];
int mid = l + r >> 1; LL ret = 0; pushdn( u );
if ( ql <= mid ) ret += qsum( u << 1, l, mid, ql, qr );
if ( mid < qr ) ret += qsum( u << 1 | 1, mid + 1, r, ql, qr );
return ret;
}
} sgt; signed main() {
n = rint(), q = rint();
sgt.build( 1, 0, n - 1 );
for ( int op, l, r; q--; ) {
op = rint(), l = rint(), r = rint();
if ( op == 1 ) sgt.add( 1, 0, n - 1, l, r, rint() );
else if ( op == 2 ) sgt.div( 1, 0, n - 1, l, r, rint() );
else if ( op == 3 ) wint( sgt.qmin( 1, 0, n - 1, l, r ) ), puts( "" );
else wint( sgt.qsum( 1, 0, n - 1, l, r ) ), puts( "" );
}
return 0;
}

Solution -「LOJ #6029」「雅礼集训 2017」市场的更多相关文章

  1. [雅礼集训 2017 Day1]市场

    link 试题分析 可以容易发现此题维护的是一个数据结构,支持区间加,区间除,区间查询最大值.其实就是在$\log$级复杂度内维护除法操作. 我们发现当除数很大或者此串序列大小差不多时,我们令$a_i ...

  2. [LOJ 6029]「雅礼集训 2017 Day1」市场

    [LOJ 6029] 「雅礼集训 2017 Day1」市场 题意 给定一个长度为 \(n\) 的数列(从 \(0\) 开始标号), 要求执行 \(q\) 次操作, 每次操作为如下四种操作之一: 1 l ...

  3. [LOJ 6031]「雅礼集训 2017 Day1」字符串

    [LOJ 6031] 「雅礼集训 2017 Day1」字符串 题意 给定一个长度为 \(n\) 的字符串 \(s\), \(m\) 对 \((l_i,r_i)\), 回答 \(q\) 个询问. 每个询 ...

  4. [LOJ 6030]「雅礼集训 2017 Day1」矩阵

    [LOJ 6030] 「雅礼集训 2017 Day1」矩阵 题意 给定一个 \(n\times n\) 的 01 矩阵, 每次操作可以将一行转置后赋值给某一列, 问最少几次操作能让矩阵全为 1. 无解 ...

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

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

  6. LOJ_6045_「雅礼集训 2017 Day8」价 _最小割

    LOJ_6045_「雅礼集训 2017 Day8」价 _最小割 描述: 有$n$种减肥药,$n$种药材,每种减肥药有一些对应的药材和一个收益. 假设选择吃下$K$种减肥药,那么需要这$K$种减肥药包含 ...

  7. 「雅礼集训 2017 Day7」事情的相似度

    「雅礼集训 2017 Day7」事情的相似度 题目链接 我们先将字符串建后缀自动机.然后对于两个前缀\([1,i]\),\([1,j]\),他们的最长公共后缀长度就是他们在\(fail\)树上对应节点 ...

  8. 「雅礼集训 2017 Day2」解题报告

    「雅礼集训 2017 Day2」水箱 我怎么知道这种题目都能构造树形结构. 根据高度构造一棵树,在树上倍增找到最大的小于约束条件高度的隔板,开一个 \(vector\) 记录一下,然后对于每个 \(v ...

  9. 「雅礼集训 2017 Day1」 解题报告

    「雅礼集训 2017 Day1」市场 挺神仙的一题.涉及区间加.区间除.区间最小值和区间和.虽然标算就是暴力,但是复杂度是有保证的. 我们知道如果线段树上的一个结点,\(max=min\) 或者 \( ...

随机推荐

  1. [转]Python3字符串前缀u、b、r

    1.无前缀 & u前缀 字符串默认创建即以Unicode编码存储,可以存储中文. string = 'a'  等效于  string = u'a' Unicode中通常每个字符由2个字节表示 ...

  2. Presto 在字节跳动的内部实践与优化

    在字节跳动内部,Presto 主要支撑了 Ad-hoc 查询.BI 可视化分析.近实时查询分析等场景,日查询量接近 100 万条.本文是字节跳动数据平台 Presto 团队-软件工程师常鹏飞在 Pre ...

  3. PAT 乙级 1004. 成绩排名 (20)(C语言描述)

    读入n名学生的姓名.学号.成绩,分别输出成绩最高和成绩最低学生的姓名和学号. 输入格式:每个测试输入包含1个测试用例,格式为 第1行:正整数n 第2行:第1个学生的姓名 学号 成绩 第3行:第2个学生 ...

  4. PkavHTTPFuzzer爆破带验证码的后台密码

    之前对暴力破解这块并没有做系统的总结,况且登录这块也是个重头戏,所以我想总结总结. 环境准备 1.用phpstudy搭建phpwms1.1.2演示环境 2.pkavhttpfuzzer工具 漏洞复现 ...

  5. leetcode 33. 搜索旋转排序数组 及 81. 搜索旋转排序数组 II

    33. 搜索旋转排序数组 问题描述 假设按照升序排序的数组在预先未知的某个点上进行了旋转. ( 例如,数组 [0,1,2,4,5,6,7] 可能变为 [4,5,6,7,0,1,2] ). 搜索一个给定 ...

  6. 如何使用Github搭建自己的博客

    1.前期准备 sudo apt-get install npm sudo npm install hexo -g 首先使用如下命令创建项目,name是你要创建的博客的名字: hexo init {na ...

  7. 【涨姿势】原来golang的case <-time.After(xxx)还有这样的坑

    偶然看到这样一篇文章:<使用 pprof 排查 Golang 内存泄露>https://www.toutiao.com/i6881796351139676680/ 最后一段让我很疑惑: 修 ...

  8. python技巧一行命令搞定局域网共享

    python超强玩法--一行命令搞定局域网共享 ​ 今天刷到python的一个新玩法,利用python自带的http服务,快速创建局域网共享服务,命令如下: python -m thhp.server ...

  9. (1)puppet安装

    简介: 基于C/S架构的Puppet更新方式一般有两种,一种是Agent端设置同步时间主动去PuppetMaster端拉取配置,另一种是通过PuppetMaster端使用puppet kick命令或者 ...

  10. 幸运转轮(Cakra)

    题目描述 lxx参加了某卫视举办的一场选秀节目,凭借曼妙的舞姿和动人的歌声,他在众多idol中脱颖而出.现在在他的面前,有四个大转轮,这四个转轮将决定他能否赢得最终大奖--出道,机会只有一次!   每 ...