P4041 [AHOI2014/JSOI2014] 奇怪的计算器

题意

给出整数 \(L,R\)\(n\) 条指令,分为 \(4\)

  1. \(+a\)\(x\rightarrow x+a\)
  2. \(-a\)\(x\rightarrow x-a\)
  3. \(\times a\)\(x\rightarrow x\times a\)
  4. \(@a\)\(x\rightarrow x+a\times x'\),其中 \(x'\) 为原始的数。

每次执行完指令后,若 \(x<L\)\(x\rightarrow L\),若 \(x>R\)\(x\rightarrow R\)
给出 \(q\) 个数求,每个数经过 \(n\) 条指令后会变成几。
\(n,q\le10^5\)\(L\le R\le 10^9\)

思路

发现对于 \(X_1\)\(X_2\),如果 \(X_1<X_2\),那么 \(X_1\) 在中间任意一部都小于等于 \(X_2\)
考虑用一棵线段树维护,把所有 \(X\) 从小到大塞进去。修改用懒标记,取 \(\min/\max\) 在树上二分。

代码

// Problem: P4041 [AHOI2014/JSOI2014] 奇怪的计算器
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/P4041
// Memory Limit: 125 MB
// Time Limit: 1000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

#include<bits/stdc++.h>
using namespace std;
namespace IO{
    template<typename T>
    inline void read(T&x){
        x=0;char c=getchar();bool f=0;
        while(!isdigit(c)) c=='-'?f=1:0,c=getchar();
        while(isdigit(c)) x=x*10+c-'0',c=getchar();
        f?x=-x:0;
    }
    template<typename T>
    inline void write(T x){
        if(x==0){putchar('0');return ;}
        x<0?x=-x,putchar('-'):0;short st[50],top=0;
        while(x) st[++top]=x%10,x/=10;
        while(top) putchar(st[top--]+'0');
    }
    inline void read(char&c){c=getchar();while(isspace(c)) c=getchar();}
    inline void write(char c){putchar(c);}
    inline void read(string&s){s.clear();char c;read(c);while(!isspace(c)&&~c) s+=c,c=getchar();}
    inline void write(string s){for(int i=0,len=s.size();i<len;i++) putchar(s[i]);}
    template<typename T>inline void write(T*x){while(*x) putchar(*(x++));}
    template<typename T,typename...T2> inline void read(T&x,T2&...y){read(x),read(y...);}
    template<typename T,typename...T2> inline void write(const T x,const T2...y){write(x),putchar(' '),write(y...),sizeof...(y)==1?putchar('\n'):0;}
}using namespace IO;
#define LL long long
const int maxn=100010;
int n,L,R,op[maxn],a[maxn],ask[maxn],q,p[maxn];
map<int,int>ans;
class Segment_Tree{
private:
    struct lazy{
        LL add,add2,mul,fz;
        lazy(){add=add2=fz=0,mul=1;}
        lazy(int _add,int _add2,int _mul,int _fz){add=_add,add2=_add2,mul=_mul,fz=_fz;}
    };
    struct node{LL min,max;lazy tag;}t[maxn*4];
    void add_tag(int u,int l,int r,lazy tag){
        if(tag.fz){
            t[u].tag.fz=t[u].min=t[u].max=tag.fz;
            t[u].tag.add=t[u].tag.add2=0;t[u].tag.mul=1;
        }
        t[u].tag.add*=tag.mul,t[u].tag.add2*=tag.mul;
        t[u].tag.mul*=tag.mul;
        t[u].tag.add+=tag.add,t[u].tag.add2+=tag.add2;
        t[u].min*=tag.mul,t[u].max*=tag.mul;
        t[u].min+=tag.add,t[u].max+=tag.add;
        t[u].min+=p[l]*tag.add2,t[u].max+=p[r]*tag.add2;
    }
    void down(int u,int l,int r){
        int mid=l+r>>1;
        add_tag(u<<1,l,mid,t[u].tag),add_tag(u<<1|1,mid+1,r,t[u].tag);
        t[u].tag=lazy();
    }
    void push_up(int u){t[u].min=min(t[u<<1].min,t[u<<1|1].min),t[u].max=max(t[u<<1].max,t[u<<1|1].max);}
    void get_min(int u,int l,int r){
        if(t[u].min>=L) return ;
        if(t[u].max<=L){add_tag(u,l,r,{0,0,1,L});return ;}
        down(u,l,r);
        int mid=l+r>>1;
        get_min(u<<1,l,mid),get_min(u<<1|1,mid+1,r);
        push_up(u);
    }
    void get_max(int u,int l,int r){
        if(t[u].max<=R) return ;
        if(t[u].min>=R){add_tag(u,l,r,{0,0,1,R});return ;}
        down(u,l,r);
        int mid=l+r>>1;
        get_max(u<<1,l,mid),get_max(u<<1|1,mid+1,r);
        push_up(u);
    }
    void get_ans(int u,int l,int r){
        if(l==r){ans[p[l]]=t[u].min;return ;}
        down(u,l,r);
        int mid=l+r>>1;
        get_ans(u<<1,l,mid),get_ans(u<<1|1,mid+1,r);
    }
public:
    void update_add(int a){add_tag(1,1,q,{a,0,1,0});}
    void update_add2(int a){add_tag(1,1,q,{0,a,1,0});}
    void update_mul(int a){add_tag(1,1,q,{0,0,a,0});}
    void update_mins(int a){add_tag(1,1,q,{-a,0,1,0});}
    void build(int u=1,int l=1,int r=q){
        if(l==r){t[u].min=t[u].max=p[l];return ;}
        int mid=l+r>>1;
        build(u<<1,l,mid),build(u<<1|1,mid+1,r);
        push_up(u);
    }
    void get_min(){get_min(1,1,q);}
    void get_max(){get_max(1,1,q);}
    void get_ans(){get_ans(1,1,q);}
    void out(int u=1,int l=1,int r=q){
        if(l==r){write(t[u].min),write(" ");return ;}
        down(u,l,r);
        int mid=l+r>>1;
        out(u<<1,l,mid),out(u<<1|1,mid+1,r);
    }
}t;
signed main(){
    read(n,L,R);
    for(int i=1;i<=n;i++){
        char x;read(x,a[i]);
        if(x=='+') op[i]=1;
        if(x=='-') op[i]=2;
        if(x=='*') op[i]=3;
        if(x=='@') op[i]=4;
    }
    read(q);
    for(int i=1;i<=q;i++) read(ask[i]),p[i]=ask[i];
    sort(p+1,p+1+q);
    t.build();
    for(int i=1;i<=n;i++){
        if(op[i]==1) t.update_add(a[i]);
        if(op[i]==2) t.update_mins(a[i]);
        if(op[i]==3) t.update_mul(a[i]);
        if(op[i]==4) t.update_add2(a[i]);
        t.get_max();
        t.get_min();
    }
    t.get_ans();
    for(int i=1;i<=q;i++) write(ans[ask[i]]),write("\n");
    return 0;
}
posted @ 2026-07-12 19:18  Link-Cut_Trees  阅读(10)  评论(0)    收藏  举报