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=" ...
随机推荐
- eclipse包层级显示和工作空间显示
本文两件事:设置包层级显示.设置工程的工作空间显示 一.各package包分层显示 平铺显示,实在不方便开发!也不方便查看工程包的层级结构,如下: 更换成层级显示: 二.工作空间显示 包用来区分类,工 ...
- AS3 注意点
当主类new 一个主影片来放内容的时候.在gc此swf时,一定要检查此主影片是否存在,如 private function initStart() { //trace("RightMenu类 ...
- 7 python 模块间相互导入
python在不同层级目录import模块的方法 注意,在python3里,即使目录下没__int__.py文件也能创建成功,猜应该是解释器优化所致,但创建包还是要记得加上这个文件 吧. 1.模块的分 ...
- ios app 生命周期
https://developer.apple.com/library/ios/documentation/iPhone/Conceptual/iPhoneOSProgrammingGuide/The ...
- python 升级到python2.7
查看python的版本 [root@localhost ~] python -V Python 2.4.3 1.先安装GCC yum -y install gcc 如果安装gcc 出错, yum ...
- ubuntu sudo apt-get upgrade 和 sudo apt-get dist-upgrade区别
sudo apt-get upgrade: 不会对系统产生重大的影响,可以在任何时候运行. sudo apt-get dist-upgrade: 涉及核心的升级,通常会对系统功能产生实际的影响,可能在 ...
- springMVC学习记录2-使用注解配置
前面说了一下使用xml配置springmvc,下面再说说注解配置.项目如下: 业务很简单,主页和输入用户名和密码进行登陆的页面. 看一下springmvc的配置文件: <?xml version ...
- 代码报错记录-MAVEN
报错: COMPILATION ERROR : 程序包不存在. 说是找不到程序包,我的JUNIT是父项目中的,子项目是从JAVA项目转为MAVEN项目的,难道在转成MAVEN项目时对POM文件的修改有 ...
- Java学习 第二节
1.非递归求第四十个斐波那契数 package test; public class fibonacci2 { public static void main(String arg[]) { ; ; ...
- ArcGIS案例学习笔记2_2
ArcGIS案例学习笔记2_2 联系方式:谢老师,135_4855_4328,xiexiaokui#qq.com 时间:第二天下午 2018年8月12日 案例1:模型构建器,山顶点提取 背景:数据量大 ...