[LOJ 6029]「雅礼集训 2017 Day1」市场
[LOJ 6029] 「雅礼集训 2017 Day1」市场
题意
给定一个长度为 \(n\) 的数列(从 \(0\) 开始标号), 要求执行 \(q\) 次操作, 每次操作为如下四种操作之一:
1 l r c给 \([l,r]\) 区间内的值全部加上 \(c\).2 l r d给 \([l,r]\) 区间内的值全部除以 \(d\), 向下取整.3 l r求 \([l,r]\) 区间内的最小值.4 l r求 \([l,r]\) 区间内的值之和.
\(n,q\le 1\times 10^5, |c|\le1\times 10^4,d\in[2,1\times 10^9]\), 时限 \(2\texttt{s}\).
题解
玄学线段树.
首先看到题目容易想到一个数最多除 $\log $ 次就会变成 \(0/1\). 但是区间加法操作让这个势能分析假掉了. (单点加法是滋磁的)
注意到在除法操作中每除一次就会导致区间内的数的浮动量 (即 \(\max - \min\)) 至少减半. 而加法操作虽然是区间操作, 但是对浮动量造成的变化只有常数个位置(两端). 而相近的一坨数整体除法可以看作是进行了一次区间加法操作.
又因为当 \(x\) 递增的时候 \(\left \lfloor \frac x d \right \rfloor\) 单调不降, 于是只要 \(\left \lfloor \frac \max d \right \rfloor - \max=\left \lfloor \frac \min d \right \rfloor -\min\), 那么整个区间产生的差值都是一样的, 都可以用一次区间加法操作代替. 而一次区间加法是 \(O(\log n)\) 的, 于是总复杂度是 \(O(q\log n\log V)\).
参考代码
#include <bits/stdc++.h>
const int MAXN=1e5+10;
typedef long long intEx;
struct Node{
int l;
int r;
int max;
int min;
int add;
intEx sum;
Node* lch;
Node* rch;
Node(int,int);
void Add(int);
void PushDown();
void Maintain();
void Add(int,int,int);
void Div(int,int,int);
int QueryMin(int,int);
intEx QuerySum(int,int);
};
int n;
int q;
int a[MAXN];
int ReadInt();
inline int FDiv(int,int);
int main(){
n=ReadInt(),q=ReadInt();
for(int i=0;i<n;i++)
a[i]=ReadInt();
Node* N=new Node(0,n-1);
for(int i=0;i<q;i++){
int t=ReadInt(),l=ReadInt(),r=ReadInt();
if(t==1){
int d=ReadInt();
N->Add(l,r,d);
}
else if(t==2){
int d=ReadInt();
N->Div(l,r,d);
}
else if(t==3)
printf("%d\n",N->QueryMin(l,r));
else if(t==4)
printf("%lld\n",N->QuerySum(l,r));
}
return 0;
}
intEx Node::QuerySum(int l,int r){
if(l<=this->l&&this->r<=r)
return this->sum;
else{
this->PushDown();
if(r<=this->lch->r)
return this->lch->QuerySum(l,r);
if(this->rch->l<=l)
return this->rch->QuerySum(l,r);
return this->lch->QuerySum(l,r)+this->rch->QuerySum(l,r);
}
}
int Node::QueryMin(int l,int r){
if(l<=this->l&&this->r<=r)
return this->min;
else{
this->PushDown();
if(r<=this->lch->r)
return this->lch->QueryMin(l,r);
if(this->rch->l<=l)
return this->rch->QueryMin(l,r);
return std::min(this->lch->QueryMin(l,r),this->rch->QueryMin(l,r));
}
}
void Node::Add(int l,int r,int d){
if(l<=this->l&&this->r<=r)
this->Add(d);
else{
this->PushDown();
if(l<=this->lch->r)
this->lch->Add(l,r,d);
if(this->rch->l<=r)
this->rch->Add(l,r,d);
this->Maintain();
}
}
void Node::Div(int l,int r,int d){
if(l<=this->l&&this->r<=r){
if(this->max-FDiv(this->max,d)==this->min-FDiv(this->min,d))
this->Add(FDiv(this->max,d)-this->max);
else{
this->PushDown();
this->lch->Div(l,r,d);
this->rch->Div(l,r,d);
this->Maintain();
}
}
else{
this->PushDown();
if(l<=this->lch->r)
this->lch->Div(l,r,d);
if(this->rch->l<=r)
this->rch->Div(l,r,d);
this->Maintain();
}
}
inline void Node::Add(int d){
this->max+=d;
this->min+=d;
this->add+=d;
this->sum+=1ll*(this->r-this->l+1)*d;
}
inline void Node::Maintain(){
this->sum=this->lch->sum+this->rch->sum;
this->max=std::max(this->lch->max,this->rch->max);
this->min=std::min(this->lch->min,this->rch->min);
}
inline void Node::PushDown(){
if(this->add!=0){
this->lch->Add(this->add);
this->rch->Add(this->add);
this->add=0;
}
}
Node::Node(int l,int r):l(l),r(r),max(a[l]),min(a[r]),add(0),sum(a[l]),lch(NULL),rch(NULL){
if(l!=r){
int mid=(l+r)>>1;
this->lch=new Node(l,mid);
this->rch=new Node(mid+1,r);
this->Maintain();
}
}
inline int ReadInt(){
int x=0,sgn=1;
register char ch=getchar();
while(!isdigit(ch)){
if(ch=='-')
sgn=-sgn;
ch=getchar();
}
while(isdigit(ch)){
x=x*10+ch-'0';
ch=getchar();
}
return x*sgn;
}
inline int FDiv(int x,int d){
if(x>=0)
return x/d;
else
return (x-d+1)/d;
}

[LOJ 6029]「雅礼集训 2017 Day1」市场的更多相关文章
- loj#6029. 「雅礼集训 2017 Day1」市场(线段树)
题意 链接 Sol 势能分析. 除法是不能打标记的,所以只能暴力递归.这里我们加一个剪枝:如果区间内最大最小值的改变量都相同的话,就变成区间减. 这样复杂度是\((n + mlogn) logV\)的 ...
- LOJ #6029. 「雅礼集训 2017 Day1」市场 线段树维护区间除法
题目描述 从前有一个贸易市场,在一位执政官到来之前都是非常繁荣的,自从他来了之后,发布了一系列奇怪的政令,导致贸易市场的衰落. 有 \(n\) 个商贩,从\(0 \sim n - 1\) 编号,每个商 ...
- #6029. 「雅礼集训 2017 Day1」市场 [线段树]
考虑到每次除法,然后加法,差距会变小,于是维护加法lazytag即可 #include <cstdio> #include <cmath> #define int long l ...
- [LOJ 6031]「雅礼集训 2017 Day1」字符串
[LOJ 6031] 「雅礼集训 2017 Day1」字符串 题意 给定一个长度为 \(n\) 的字符串 \(s\), \(m\) 对 \((l_i,r_i)\), 回答 \(q\) 个询问. 每个询 ...
- [LOJ 6030]「雅礼集训 2017 Day1」矩阵
[LOJ 6030] 「雅礼集训 2017 Day1」矩阵 题意 给定一个 \(n\times n\) 的 01 矩阵, 每次操作可以将一行转置后赋值给某一列, 问最少几次操作能让矩阵全为 1. 无解 ...
- loj 6031「雅礼集训 2017 Day1」字符串
loj 注意到每次询问串长度都是给定的,并且询问串长\(k*\)询问次数\(q<10^5\),所以这里面一个东西大的时候另一个东西就小,那么考虑对较小的下功夫 如果\(k\le \sqrt{n} ...
- loj#6031. 「雅礼集训 2017 Day1」字符串(SAM 广义SAM 数据分治)
题意 链接 Sol \(10^5\)次询问每次询问\(10^5\)个区间..这种题第一感觉就是根号/数据分治的模型. \(K\)是个定值这个很关键. 考虑\(K\)比较小的情况,可以直接暴力建SAM, ...
- loj#6030. 「雅礼集训 2017 Day1」矩阵(贪心 构造)
题意 链接 Sol 自己都不知道自己怎么做出来的系列 不难观察出几个性质: 最优策略一定是先把某一行弄黑,然后再用这一行去覆盖不是全黑的列 无解当且仅当无黑色.否则第一个黑色所在的行\(i\)可以先把 ...
- loj6029 「雅礼集训 2017 Day1」市场
传送门:https://loj.ac/problem/6029 [题解] 考虑如果有一些近似连续的段 比如 2 2 2 3 3 3,考虑在除3意义下,变成0 0 0 1 1 1,相当于整体-2 又:区 ...
随机推荐
- 解决webstorm本地IP访问页面出错的问题
想在手机端访问webstorm做出的页面,遇到了根据IP地址访问页面错误的问题,试了网上的方法:“设置webstorm可以被外部连接访问”,依旧不能解决 解决方法: 在webstorm下:ctrl+a ...
- UVa 442 Matrix Chain Multiplication(栈的应用)
题目链接: https://cn.vjudge.net/problem/UVA-442 /* 问题 输入有括号表示优先级的矩阵链乘式子,计算该式进行的乘法次数之和 解题思路 栈的应用,直接忽视左括号, ...
- flex弹性布局学习总结
本文首次发布在我的个人博客:Claiyre的个人博客 https://claiyre.github.io/ 博客园地址:http://www.cnblogs.com/nuannuan7362/如需转载 ...
- 控制器中获取Field值
在ASP.NET MVC程序中,我们需要POST Data到制器中,是有很多方法.但是我们想在控制器中,获取Feild值呢?怎样获取?你可以留意到有一个类FormCollection.它能帮助到我们解 ...
- python安装过程的一些问题解决方案
1. pip升级后出现提示信息 DEPRECATION: The default format will switch to columns in the future. You can use –f ...
- [日常] Go语言圣经-Goroutines和线程
Goroutines和线程: 1.动态栈: 1)线程都有一个固定大小的内存块(一般会是2MB)来做栈 2)一个goroutine会以一个很小的栈开始其生命周期,一般只需要2KB,不是固定的:栈的大小会 ...
- java基础-基础语法
一.标识符 java中对各种变量.方法和类等要素命名的时候使用的字符序列称为标识符. java中标识符的命名规则:1.由字母.数字.下划线(_)以及美元符号($)组成 2.标识符应该以字母或者下划线开 ...
- Charlie's Change(完全背包+路径记忆)
Charlie's Change Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 3176 Accepted: 913 D ...
- JavaScript--DOM进阶(20)
// DOM自身存在很多类型,在上一章中有介绍,比如Element类型:表示的是元素节点;再比如Text类型;表示的是文本节点; 一 DOM类型 类型名 说明 Node 表示所有类型值的统一接口,IE ...
- vue 子组件和父组件
作者QQ:1095737364 QQ群:123300273 欢迎加入! 1.添加子组件 1.父组件修改 <template> <!-- v-for 表情表示循环输出数据 ...