2018.07.25 bzoj3878: [Ahoi2014&Jsoi2014]奇怪的计算器(线段树)
传送门
线段树综合。
让我想起一道叫做siano" role="presentation" style="position: relative;">sianosiano的题,这题就是那题的强化版本。
说说做法吧:
跟siano" role="presentation" style="position: relative;">sianosiano一样,当我们把a[i]" role="presentation" style="position: relative;">a[i]a[i]排成有序的之后,就会保证在若干次操作后整个数列仍然是单调的。
首先加减可以看成一个操作,L,R" role="presentation" style="position: relative;">L,RL,R的限制也只相当于一个操作,因此这道题要我们维护这几个操作:
1.区间加
2.区间乘
3.区间加变形(加上原数a[i]" role="presentation" style="position: relative;">a[i]a[i]的k" role="presentation" style="position: relative;">kk倍)
4.区间覆盖
维护:区间最大最小,单点值。
因此我们可以设计一个神奇的更新函数f(p,k1,k2,k3)" role="presentation" style="position: relative;">f(p,k1,k2,k3)f(p,k1,k2,k3),表示整个区间的值的变化方式:
c[i]=c[i]∗k1+k2∗a[i]+k3" role="presentation" style="position: relative;">c[i]=c[i]∗k1+k2∗a[i]+k3c[i]=c[i]∗k1+k2∗a[i]+k3,然后我们又可以惊奇的发现这个函数可以用于所有的区间修改函数。
1.区间加:f(p,1,0,add)" role="presentation" style="position: relative;">f(p,1,0,add)f(p,1,0,add)。
2.区间乘:f(p,mul,0,0)" role="presentation" style="position: relative;">f(p,mul,0,0)f(p,mul,0,0)。
3.区间加变形:f(p,1,addx,0)" role="presentation" style="position: relative;">f(p,1,addx,0)f(p,1,addx,0)。
4.区间覆盖:f(p,0,0,set)" role="presentation" style="position: relative;">f(p,0,0,set)f(p,0,0,set)。
这样的话,我们连前三个操作的单独的修改函数都不用写,简洁自然。
代码如下:
#include<bits/stdc++.h>
#define ll long long
#define N 100005
#define lc (p<<1)
#define rc (p<<1|1)
#define p1 T[p].lz1
#define p2 T[p].lz2
#define p3 T[p].lz3
#define mid (T[p].l+T[p].r>>1)
using namespace std;
struct Node{int l,r;ll mn,mx,lz1,lz2,lz3;}T[N<<2];
struct Query{int op;ll v;}q[N];
struct Ans{int id;ll v;}a[N];
int n,m;
ll ans[N],L,R;
inline ll max(ll a,ll b){return a>b?a:b;}
inline ll min(ll a,ll b){return a<b?a:b;}
inline void pushup(int p){T[p].mx=T[rc].mx,T[p].mn=T[lc].mn;}
inline void pushnow(int p,ll k1,ll k2,ll k3){
p1*=k1,p2=p2*k1+k2,p3=p3*k1+k3;
T[p].mx=T[p].mx*k1+k2*a[T[p].r].v+k3;
T[p].mn=T[p].mn*k1+k2*a[T[p].l].v+k3;
}
inline void pushdown(int p){pushnow(lc,p1,p2,p3),pushnow(rc,p1,p2,p3),p1=1,p2=0,p3=0;}
inline void build(int p,int l,int r){
T[p].l=l,T[p].r=r,p1=1,p2=p3=0,T[p].mx=a[r].v,T[p].mn=a[l].v;
if(l==r)return;
build(lc,l,mid),build(rc,mid+1,r);
}
inline void modify1(int p){
if(T[p].l==T[p].r)return pushnow(p,0,0,L);
pushdown(p);
if(T[rc].mn<L)pushnow(lc,0,0,L),modify1(rc);
else modify1(lc);
pushup(p);
}
inline void modify2(int p){
if(T[p].l==T[p].r)return pushnow(p,0,0,R);
pushdown(p);
if(T[lc].mx>R)pushnow(rc,0,0,R),modify2(lc);
else modify2(rc);
pushup(p);
}
inline bool cmp(Ans a,Ans b){return a.v<b.v;}
inline void query(int p){
if(T[p].l==T[p].r){ans[a[T[p].l].id]=T[p].mn;return;}
pushdown(p),query(lc),query(rc);
}
int main(){
scanf("%d%lld%lld",&m,&L,&R);
for(int i=1;i<=m;++i){
char s[2];
scanf("%s%lld",s,&q[i].v);
switch(s[0]){
case '+':{q[i].op=1;break;}
case '-':{q[i].op=2;break;}
case '*':{q[i].op=3;break;}
default:{q[i].op=4;break;}
}
}
scanf("%d",&n);
for(int i=1;i<=n;++i)scanf("%lld",&a[i].v),a[i].id=i;
sort(a+1,a+n+1,cmp),build(1,1,n);
for(int i=1;i<=m;++i){
switch(q[i].op){
case 1:{pushnow(1,1,0,q[i].v);break;}
case 2:{pushnow(1,1,0,-q[i].v);break;}
case 3:{pushnow(1,q[i].v,0,0);break;}
default:{pushnow(1,1,q[i].v,0);break;}
}
if(T[1].mn<L)modify1(1);
if(T[1].mx>R)modify2(1);
}
query(1);
for(int i=1;i<=n;++i)cout<<ans[i]<<'\n';
return 0;
}
2018.07.25 bzoj3878: [Ahoi2014&Jsoi2014]奇怪的计算器(线段树)的更多相关文章
- BZOJ3878: [Ahoi2014&Jsoi2014]奇怪的计算器
BZOJ3878: [Ahoi2014&Jsoi2014]奇怪的计算器 Description [故事背景] JYY有个奇怪的计算器,有一天这个计算器坏了,JYY希望你能帮助他写 一个程序来模 ...
- BZOJ 3878 [AHOI&JSOI2014]奇怪的计算器 (线段树)
题面:BZOJ传送门 洛谷传送门 线段树好题 题目保证$a$一定是正整数,容易发现计算结果是单调的 我们把询问离线,并按照从小到大排序 某次操作可能导致某些位置达到边界$L/R$ 根据单调性的结论 这 ...
- AHOI2014/JSOI2014 奇怪的计算器
题目描述 题解: 考虑到经过一系列变化后小数不可能比大数大,我们可以用线段树维护区间修改. 重点是,每个节点都可以通过$a[i]=a[i]*t1+a0[i]*t2+t3$这个函数来表示,我们就可以把三 ...
- 2018.07.27 bzoj3064: Tyvj 1518 CPU监控(线段树)
传送门 线段树好题. 维护区间加,区间覆盖,区间最大,区间历史最大. 这个东西在国家集训队2016论文集之<区间最值操作与历史最值问题--杭州学军中学 吉如一>中讲的已经很详细了. 简单来 ...
- 2018.07.27 bzoj4695: 最假女选手(线段树)
传送门 线段树好题 支持区间加,区间取min" role="presentation" style="position: relative;"> ...
- 2018宁夏邀请赛 L Continuous Intervals(单调栈+线段树)
2018宁夏邀请赛 L Continuous Intervals(单调栈+线段树) 传送门:https://nanti.jisuanke.com/t/41296 题意: 给一个数列A 问在数列A中有多 ...
- BZOJ 3878 【AHOI2014】 奇怪的计算器
题目链接:奇怪的计算器 如果没有溢出的话,所有的标记都可以在线段树上直接维护,所以一棵线段树就解决问题了. 现在有了溢出,怎么办呢? 发现就算溢出了,各个元素的相对大小关系也是不变的.所以,如果一开始 ...
- 【2018.06.26NOIP模拟】T1纪念碑square 【线段树】*
[2018.06.26NOIP模拟]T1纪念碑square 题目描述 2034年,纪念中学决定修建校庆100周年纪念碑,作为杰出校友的你被找了过来,帮校方确定纪念碑的选址. 纪念中学的土地可以看作是一 ...
- 2018.07.25 bzoj2125: 最短路(圆方树+倍增)
传送门 人生的第一道仙人掌. 这道题求是仙人掌上的最短路. 先建出圆方树,然后用倍增跑最短路,当lca" role="presentation" style=" ...
随机推荐
- PHP依赖注入(DI)和控制反转(IoC)详解
这篇文章主要介绍了PHP依赖注入(DI)和控制反转(IoC)的相关资料,具有一定的参考价值,感兴趣的小伙伴们可以参考一下 首先依赖注入和控制反转说的是同一个东西,是一种设计模式,这种设计模式用来减少程 ...
- JavaScript加法
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <hea ...
- AS3 在不规则区域内拖动
原理: 1.确保拖动对象在鼠标点上,如果不确定会出现瞬间移动的感觉 2.确保触碰到非通行区域,跳回到没触碰的点 源码: import flash.events.MouseEvent; import f ...
- 在linux中运行main方法所在的java类(亲测有效!!!)
本人是用SecureCRTPortable连接linux终端的.其他工具连接linux终端应该是一样的操作! 一.首先到移动到java工程所在的bin目录. 二.在bin目录下执行javac -cp ...
- PCM 编码
PCM编码,即无损编码(抽样->量化->编码) 这里的 无损 是个广义概念,任何数字编码都有损,只不过PCM的“损”最小:通常所说的无损编码都是指PCM编码 wav音频参数: 最重要的三个 ...
- hadoop配置文件的参数含义说明
#hadoop version 查看版本号 1 .获取默认配置 hadoop2系列配置文件一共包括6个,分别是hadoop-env.sh.core-site.xml.hdfs-site.xml.map ...
- Oracle CHAR,VARCHAR,VARCHAR2,nvarchar类型的区别与使用(转载)
一 varchar,varchar2,nvarchar,nvarchar2 四个类型都属于变长字符类型, varchar和varchar2的区别在与后者把所有字符都占两字节,前者只对汉字和全角等字符占 ...
- 孤岛营救问题(BFS+状压DP)
孤岛营救问题 https://www.luogu.org/problemnew/show/P4011 用状压DP标记拿到钥匙的数量 #include<iostream> #include& ...
- phpStudy3——往数据库中添加数据
前言: 前边介绍了查询数据库的方法,这里介绍下往数据库中添加数据的方法. 项目需求: 用户在前端页面输入的用户名和手机号码,点击提交后后端判断手机号码是否已经存在.如果不存在,那么插入数据库到数据库, ...
- 安装配置Windows Live Writer做为博客客户端
前言: 国内好些空间.博客是支持Windows Live Writer客户端的,也就是说使用Windows Live Writer不用登陆博客网站,就可以向不同的博客网站发布博客了. Windows ...