P4041 [AHOI2014/JSOI2014] 奇怪的计算器
题意
给出整数 \(L,R\) 和 \(n\) 条指令,分为 \(4\) 种
- \(+a\):\(x\rightarrow x+a\)
- \(-a\):\(x\rightarrow x-a\)
- \(\times a\):\(x\rightarrow x\times a\)
- \(@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;
}

浙公网安备 33010602011771号