奇怪的计算器题解

奇怪的计算器题解

首先:输入\(q\)个数进行一样的操作?
->区间[1,q]的修改。
'*,+,-,@'操作?
->线段树区间修改。
但这题比较秀。
总结起来有四个操作:
1.区间+(-变为加相反数)
2.区间×
3.区间+原数的倍数
4.区间覆盖(<l,或>r)
这四个操作要求我们记载5个变量,区间最小值、最大值,前3个操作的lazy标记,
但我们发现:原数大的经过一样的操作后的数也比其他操作后的数大,
故我们可以将原数排序,那么区间最小值一定是最左边的值,最大值一定在最右边,这样修改就十分方便了。
这里的修改我单独写了个函数,方便了很多。

#include<bits/stdc++.h>
#define LL long long 
#define ly1 t[x].lazy1
#define ly2 t[x].lazy2
#define ly3 t[x].lazy3
#define Mx t[x].mx
#define Mn t[x].mn
#define L t[x].l
#define R t[x].r
#define lc x<<1
#define rc x<<1|1
using namespace std;
const int N=1e5+7;
int n,m,ll,rr,op[N],q[N],ans[N];
char c[12];
struct xd{int z,i;}o[N];
struct tree{int l,r; LL mn,mx,lazy1,lazy2,lazy3;}t[N<<2];
inline int read(){
   int T=0,F=1; char ch=getchar();
   while(ch<'0'||ch>'9'){if(ch=='-') F=-1; ch=getchar();}
   while(ch>='0'&&ch<='9') T=(T<<3)+(T<<1)+(ch-48),ch=getchar();
   return F*T; 
}
inline void work(int x,LL a,LL b,LL c){
   ly1*=a,ly2=ly2*a+b,ly3=ly3*a+c;
   Mx=Mx*a+o[R].z*b+c,Mn=Mn*a+o[L].z*b+c;
}
inline void pushdown(int x){work(lc,ly1,ly2,ly3),work(rc,ly1,ly2,ly3),ly1=1,ly2=0,ly3=0;}
void build(int l,int r,int x){
    L=l,R=r,ly1=1,ly2=0,ly3=0,Mx=o[r].z,Mn=o[l].z;
    if(l==r) return;
    int mid=l+r>>1;
    build(l,mid,lc),build(mid+1,r,rc);
}
void update(int x){
    if(L==R){work(x,0,0,ll); return;}
    pushdown(x);
    if(t[rc].mn<ll) work(lc,0,0,ll),update(rc);
    else update(lc);
    Mx=t[rc].mx,Mn=t[lc].mn;
}
void update2(int x){
    if(L==R){work(x,0,0,rr); return;}
    pushdown(x);
    if(t[lc].mx>rr) work(rc,0,0,rr),update2(lc);
    else update2(rc);
    Mx=t[rc].mx,Mn=t[lc].mn;
}
bool cmp(xd u,xd v){return u.z<v.z;}
void get_ans(int x){
    if(L==R){ans[o[L].i]=Mn; return;}
    pushdown(x),get_ans(lc),get_ans(rc);
}
int main(){
   m=read(),ll=read(),rr=read();
   for(int i=1;i<=m;++i){
       scanf("%s",c),q[i]=read();
       if(c[0]=='+') op[i]=1;
       else if(c[0]=='-') op[i]=1,q[i]=-q[i];
       else if(c[0]=='*') op[i]=2;
       else op[i]=3;
   }
   n=read();
   for(int i=1;i<=n;++i) o[i].i=i,o[i].z=read();
   sort(o+1,o+n+1,cmp),build(1,n,1);
   for(int i=1;i<=m;++i){
       if(op[i]==1) work(1,1,0,q[i]);
       else if(op[i]==2) work(1,q[i],0,0);
       else work(1,1,q[i],0);
       if(t[1].mn<ll) update(1);
       if(t[1].mx>rr) update2(1); 
   }
   get_ans(1);
   for(int i=1;i<=n;++i) printf("%d\n",ans[i]);
   return 0;
}

猜你喜欢

转载自www.cnblogs.com/ljk123-de-bo-ke/p/11853294.html