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=" ...
随机推荐
- IOS HTTP访问端口
Project dyld_sim raised exception class ENetHTTPClientException with message 'Error -1022 accessing ...
- AJAX服务器返回数据 连接数据库查询数据
getcustomer.asp" 中的源代码负责对数据库进行查询,然后用 HTML 表格返回结果: <% response.expires=-1 sql="SELECT * ...
- 在spring引入log4j(非web项目)
https://blog.csdn.net/u012578322/article/details/78012183 在spring中使用log4j 引入log4j软件包 配置log4j属性 加载log ...
- mime设置
ie9对mime有特殊要求,必须要有type才可以. 如果出现css的mime类型不支持.则没有加 type="css/text" 查看本机的mime支持: regedit > ...
- 【转】.net 实现 语音搜索(仅限WebKit内核浏览器)
<input type="text" class="text" name="value_2" id="value_2&quo ...
- 播放一个wav文件
use mmsystem;SndPlaySound('hello.wav',SND_FILENAME or SND_SYNC) ///////////////////////////////////u ...
- Numpy 常用函数
保存文件i3 = eye(3) 创建一个3*3 的单位矩阵savetxt('eye.txt',i3) #保存矩阵 读取文件c,v=np.loadtxt('data.csv', delimiter=', ...
- java列表转成 int[] 的格式
java 稀疏矩阵中输入的索引系列和对应的值系列需要用 int[] r_indices = new int[featureIdxList.size()]; 的数据格式. 但是实际中可能实现没法确定 f ...
- 登录时显示403 Access Denied
用户名及密码设置如下: 在tomcat安装目录\conf\tomcat-users.xml中的<tomcat-users>标签内设置: <role rolename="ma ...
- 自定义事件 js
// 原理如下// 创建 类型为HTMLEvents的事件 var evt = document.createEvent("HTMLEvents"); // 初始化 自定义eee ...