【LOJ#6029】市场(线段树)
【LOJ#6029】市场(线段树)
题面
题解
看着就是一个需要势能分析的线段树。
不难发现就是把第二个整除操作化为减法。
考虑一下什么时候整除操作才能变成减法。
假设两个数为\(a,b\)。那么就有\(\displaystyle a-[\frac{a}{d}]=b-[\frac{b}{d}]\)。
那么假设\(a,b\)整除的结果分别为\(aa,bb\)。\(a=d*aa+p_a,b=d*bb+p_b\)
得到:\(\displaystyle (d-1)aa+p_a=(d-1)bb+p_b\)
化简后得到:\(\displaystyle (d-1)(aa-bb)=p_b-p_a\)
显然\(p_a,p_b\)的取值范围就是\([0,d)\),而左边还乘了一个\(d-1\)。也就意味着这个限制是非常强的,假设\(aa>bb\)(等于就必定相等了,没什么好考虑的),那么\(p_b-p_b\in[0,d)\)。左边显然只能取\(1\),右边显然只能去\(d-1\)。写出来就是:\(a=d*aa,b=d*(aa-1)+d-1\)。所以我们得到\(a-b=1\)。
因此维护区间最大值和最小值,如果最大值和最小值整除操作之后的差相等,那么可以变为区间减法。否则暴力下放。
至于复杂度?听\(zsy\)口胡了一下他的分析。单独考虑一个线段树节点,它最多被暴力访问\(loga\)次。如果区间加法则重置这个\(log\)。而每次区间加法最多影响\(logn\)个区间,也就是会重置\(logn\)个区间的访问次数。而\(m\)次操作最多重置\(mlogn\)个区间,因此最多增加访问次数是\(loga\)次。所以总的复杂度就是\(O((n+mlogn)loga)\)。
感觉很对的样子。
注意一下负数的向下取整。
#include<iostream>
#include<cstdio>
using namespace std;
#define ll long long
#define MAX 100100
#define lson (now<<1)
#define rson (now<<1|1)
inline int read()
{
int x=0;bool t=false;char ch=getchar();
while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
if(ch=='-')t=true,ch=getchar();
while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
return t?-x:x;
}
struct Node{ll v;int mn,mx,tag;}t[MAX<<2];
void pushup(int now)
{
t[now].mn=min(t[lson].mn,t[rson].mn);
t[now].mx=max(t[lson].mx,t[rson].mx);
t[now].v=t[lson].v+t[rson].v;
}
void Build(int now,int l,int r)
{
if(l==r){t[now].v=t[now].mn=t[now].mx=read();return;}
int mid=(l+r)>>1;
Build(lson,l,mid);Build(rson,mid+1,r);
pushup(now);
}
void puttag(int now,int l,int r,int w)
{
t[now].v+=(r-l+1)*w;
t[now].tag+=w;t[now].mn+=w;t[now].mx+=w;
}
void pushdown(int now,int l,int r)
{
if(!t[now].tag)return;
int mid=(l+r)>>1;
puttag(lson,l,mid,t[now].tag);
puttag(rson,mid+1,r,t[now].tag);
t[now].tag=0;
}
void Modify(int now,int l,int r,int L,int R,int w)
{
if(L<=l&&r<=R){puttag(now,l,r,w);return;}
int mid=(l+r)>>1;pushdown(now,l,r);
if(L<=mid)Modify(lson,l,mid,L,R,w);
if(R>mid)Modify(rson,mid+1,r,L,R,w);
pushup(now);
}
int Div(int a,int d)
{
if(a>=0)return a/d-a;
if(a%d==0)return a/d-a;
return a/d-1-a;
}
void ModifyDiv(int now,int l,int r,int L,int R,int d)
{
if(L<=l&&r<=R)
if(Div(t[now].mx,d)==Div(t[now].mn,d))
{puttag(now,l,r,Div(t[now].mx,d));return;}
int mid=(l+r)>>1;pushdown(now,l,r);
if(L<=mid)ModifyDiv(lson,l,mid,L,R,d);
if(R>mid)ModifyDiv(rson,mid+1,r,L,R,d);
pushup(now);
}
ll Query(int now,int l,int r,int L,int R)
{
if(L<=l&&r<=R)return t[now].v;
int mid=(l+r)>>1;pushdown(now,l,r);
ll ret=0;
if(L<=mid)ret+=Query(lson,l,mid,L,R);
if(R>mid)ret+=Query(rson,mid+1,r,L,R);
return ret;
}
int Querymn(int now,int l,int r,int L,int R)
{
if(L==l&&r==R)return t[now].mn;
int mid=(l+r)>>1;pushdown(now,l,r);
if(R<=mid)return Querymn(lson,l,mid,L,R);
if(L>mid)return Querymn(rson,mid+1,r,L,R);
return min(Querymn(lson,l,mid,L,mid),Querymn(rson,mid+1,r,mid+1,R));
}
int n,Q;
int main()
{
n=read();Q=read();
Build(1,1,n);
while(Q--)
{
int opt=read(),l=read()+1,r=read()+1;
if(opt==1)Modify(1,1,n,l,r,read());
if(opt==2)ModifyDiv(1,1,n,l,r,read());
if(opt==3)printf("%d\n",Querymn(1,1,n,l,r));
if(opt==4)printf("%lld\n",Query(1,1,n,l,r));
}
return 0;
}
【LOJ#6029】市场(线段树)的更多相关文章
- LOJ #6029. 「雅礼集训 2017 Day1」市场 线段树维护区间除法
题目描述 从前有一个贸易市场,在一位执政官到来之前都是非常繁荣的,自从他来了之后,发布了一系列奇怪的政令,导致贸易市场的衰落. 有 \(n\) 个商贩,从\(0 \sim n - 1\) 编号,每个商 ...
- 【loj6029】「雅礼集训 2017 Day1」市场 线段树+均摊分析
题目描述 给出一个长度为 $n$ 的序列,支持 $m$ 次操作,操作有四种:区间加.区间下取整除.区间求最小值.区间求和. $n\le 100000$ ,每次加的数在 $[-10^4,10^4]$ 之 ...
- 【题解】【LibreOJ Round #6】花团 LOJ 534 时间线段树分治 背包
Prelude 题目链接:萌萌哒传送门(/≧▽≦)/ Solution 如果完全离线的话,可以直接用时间线段树分治来做,复杂度\(O(qv \log q)\). 现在在线了怎么办呢? 这其实是个假在线 ...
- loj#6029. 「雅礼集训 2017 Day1」市场(线段树)
题意 链接 Sol 势能分析. 除法是不能打标记的,所以只能暴力递归.这里我们加一个剪枝:如果区间内最大最小值的改变量都相同的话,就变成区间减. 这样复杂度是\((n + mlogn) logV\)的 ...
- #6029. 「雅礼集训 2017 Day1」市场 [线段树]
考虑到每次除法,然后加法,差距会变小,于是维护加法lazytag即可 #include <cstdio> #include <cmath> #define int long l ...
- 「雅礼集训 2017 Day1」市场 (线段树除法,区间最小,区间查询)
老师说,你们暴力求除法也整不了多少次就归一了,暴力就好了(应该只有log(n)次) 于是暴力啊暴力,结果我归天了. 好吧,在各种题解的摧残下,我终于出了一篇巨好看(chou lou)代码(很多结构体党 ...
- [LOJ 6029]「雅礼集训 2017 Day1」市场
[LOJ 6029] 「雅礼集训 2017 Day1」市场 题意 给定一个长度为 \(n\) 的数列(从 \(0\) 开始标号), 要求执行 \(q\) 次操作, 每次操作为如下四种操作之一: 1 l ...
- LOJ#3043.【ZJOI2019】 线段树 线段树,概率期望
原文链接www.cnblogs.com/zhouzhendong/p/ZJOI2019Day1T2.html 前言 在LOJ交了一下我的代码,发现它比选手机快将近 4 倍. 题解 对于线段树上每一个节 ...
- LOJ.2864.[IOI2018]排座位(线段树)
LOJ 洛谷 先令编号从\(1\)开始.我们要求\([1,i]\)这些数字能否构成一个矩形. 考虑能否用线段树维护,让每个叶子节点\(i\)表示前\(i\)个数能否构成矩形. 一种方法是维护前\(i\ ...
随机推荐
- Django lazy load 懒加载 倒序查询
Django orm默认懒加载 Django orm默认使用的懒加载,即使用的时候才去访问数据库,且每次默认取最少的数据,当然这样有好处也有坏处... 坏处: 会导致频繁的查询数据库,如涉及到外键 ...
- docker redis 多个实例
Docker运维笔记-Docker端口映射 - 恶性佛 - CSDN博客https://blog.csdn.net/qq_29994609/article/details/51730640 利用 Do ...
- # 【Python3练习题 007】 有一对兔子,从出生后第3个月起每个月都生一对兔子, # 小兔子长到第三个月后每个月又生一对兔子, # 假如兔子都不死,问每个月的兔子总数为多少?
# 有一对兔子,从出生后第3个月起每个月都生一对兔子,# 小兔子长到第三个月后每个月又生一对兔子, # 假如兔子都不死,问每个月的兔子总数为多少?这题反正我自己是算不出来.网上说是经典的“斐波纳契数列 ...
- C#复习笔记(4)--C#3:革新写代码的方式(扩展方法)
扩展方法 扩展方法有以下几个需求: 你想为一个类型添加一些 成员: 你不需要为类型的实例添加任何更多的数据: 你不能改变类型本身, 因为是别人的代码. 对于C#1和C#2中的静态方法,扩展方法是一种更 ...
- Java 找不到或者无法加载主类
1 测试Test 类的时候突然遇到一个很奇怪的问题,网上搜了很多资料才找到解决办法,大多数情况是因为类加了包名编译,执行的时候没有到包下去执行.与我遇到的情况不一样. 问题:写了一个测试类Test,在 ...
- MySQL dump文件导入
1 打开cmd 输入要导入的数据库,用户名,密码,dump文件路径 mysql -u employees <E:\employees_db\load_departments.dump
- Azure系列2.1.13 —— CloudBlockBlob
(小弟自学Azure,文中有不正确之处,请路过各位大神指正.) 网上azure的资料较少,尤其是API,全是英文的,中文资料更是少之又少.这次由于公司项目需要使用Azure,所以对Azure的一些学习 ...
- [转帖]BRD、MRD 和 PRD
来源: https://www.zhihu.com/question/19655491 BRD 商业需求文档 Business Requirement Document MRD 市场需求文档 Mark ...
- Day 5-6 反射和内置方法之item系列
python面向对象中的反射:通过字符串的形式操作对象相关的属性.python中的一切事物都是对象(都可以使用反射) #!_*_ coding:utf-8 _*_ class People: def ...
- python try except else finally
python try except else finally 实例 class AError(Exception): """AError---exception&quo ...