传送门

线段树综合。

让我想起一道叫做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]奇怪的计算器(线段树)的更多相关文章

  1. BZOJ3878: [Ahoi2014&Jsoi2014]奇怪的计算器

    BZOJ3878: [Ahoi2014&Jsoi2014]奇怪的计算器 Description [故事背景] JYY有个奇怪的计算器,有一天这个计算器坏了,JYY希望你能帮助他写 一个程序来模 ...

  2. BZOJ 3878 [AHOI&JSOI2014]奇怪的计算器 (线段树)

    题面:BZOJ传送门 洛谷传送门 线段树好题 题目保证$a$一定是正整数,容易发现计算结果是单调的 我们把询问离线,并按照从小到大排序 某次操作可能导致某些位置达到边界$L/R$ 根据单调性的结论 这 ...

  3. AHOI2014/JSOI2014 奇怪的计算器

    题目描述 题解: 考虑到经过一系列变化后小数不可能比大数大,我们可以用线段树维护区间修改. 重点是,每个节点都可以通过$a[i]=a[i]*t1+a0[i]*t2+t3$这个函数来表示,我们就可以把三 ...

  4. 2018.07.27 bzoj3064: Tyvj 1518 CPU监控(线段树)

    传送门 线段树好题. 维护区间加,区间覆盖,区间最大,区间历史最大. 这个东西在国家集训队2016论文集之<区间最值操作与历史最值问题--杭州学军中学 吉如一>中讲的已经很详细了. 简单来 ...

  5. 2018.07.27 bzoj4695: 最假女选手(线段树)

    传送门 线段树好题 支持区间加,区间取min" role="presentation" style="position: relative;"> ...

  6. 2018宁夏邀请赛 L Continuous Intervals(单调栈+线段树)

    2018宁夏邀请赛 L Continuous Intervals(单调栈+线段树) 传送门:https://nanti.jisuanke.com/t/41296 题意: 给一个数列A 问在数列A中有多 ...

  7. BZOJ 3878 【AHOI2014】 奇怪的计算器

    题目链接:奇怪的计算器 如果没有溢出的话,所有的标记都可以在线段树上直接维护,所以一棵线段树就解决问题了. 现在有了溢出,怎么办呢? 发现就算溢出了,各个元素的相对大小关系也是不变的.所以,如果一开始 ...

  8. 【2018.06.26NOIP模拟】T1纪念碑square 【线段树】*

    [2018.06.26NOIP模拟]T1纪念碑square 题目描述 2034年,纪念中学决定修建校庆100周年纪念碑,作为杰出校友的你被找了过来,帮校方确定纪念碑的选址. 纪念中学的土地可以看作是一 ...

  9. 2018.07.25 bzoj2125: 最短路(圆方树+倍增)

    传送门 人生的第一道仙人掌. 这道题求是仙人掌上的最短路. 先建出圆方树,然后用倍增跑最短路,当lca" role="presentation" style=" ...

随机推荐

  1. 从底层谈WebGIS 原理设计与实现(六):WebGIS中地图瓦片在Canvas上的拼接显示原理

    从底层谈WebGIS 原理设计与实现(六):WebGIS中地图瓦片在Canvas上的拼接显示原理 作者:naaoveGI…    文章来源:naaoveGIS    点击数:1145    更新时间: ...

  2. ubuntu 安装u盘恢复

    XP下进入CMD命令窗体,Vista及7/8下右键以管理员方式运行DOS窗体(win8.1:开始屏幕-windows系统-命令提示符) 输入DISKPART,会显示计算机名,及DISKPART> ...

  3. Java LinkList遍历方式

    1.LinkedList的遍历方式 a.一般的for循环(随机访问) int size = list.size(); for (int i=0; i<size; i++) { list.get( ...

  4. avalon的常见问题

    随着avalon的普及,越来越多人加入avalon的大家庭.随之而来的是各种问题.本文在这里统一解答一下. 使用avalon基本上有几个方针要坚持 数据必须先定义后使用,只能VM中定义,不能V中定义. ...

  5. [故障引起的故事]URL中带加号的处理

    问题起因:      客户订购了一关键字为"e+h 变送器" , 在首页推荐广告中,会根据用户在search 搜索过的关键字进行一个匹配投放.技术实现是UED 通过JS 获取coo ...

  6. css中选择器

    css中常用的选择器有: 1.元素选择器:h1{}  如<h1></h1> 2.类选择器:.test{}或者h1.test{} 如<h1 class="test ...

  7. JAVA的String类的常用方法(转载)

    Java-String类的常用方法总结   一.String类String类在java.lang包中,java使用String类创建一个字符串变量,字符串变量属于对象.java把String类声明的f ...

  8. 疯狂JAVA——第二章 理解面向对象

    面向对象的三大特征:继承.封装和多态 面向对象的方式实际上由OOA(面向对象分析).OOD(面向对象设计)和OOP(面相对象编程)三个部分组成,其中OOA和OOD的结构需要用一个描述方式来描述并记录, ...

  9. rabbitmq web管理界面 用户管理

    安装最新版本的rabbitmq(3.3.1),并启用management plugin后,使用默认的账号guest登陆管理控制台,却提示登陆失败. 翻看官方的release文档后,得知由于账号gues ...

  10. linux 随笔

    LINUX环境下的批处理文件的扩展名是.sh,而在windows环境的批处理文件名是.bat