bzoj 3878: [Ahoi2014]奇怪的计算器

Description

 【故事背景】

JYY有个奇怪的计算器,有一天这个计算器坏了,JYY希望你能帮助他写
一个程序来模拟这个计算器的运算。
【问题描述】
JYY的计算器可以执行N条预设好的指令。每次JYY向计算器输入一个正
整数X,计算器就会以X作为初始值,接着依次执行预设的N条指令,最后把
最终得出的结果返回给JYY。
每一条指令可以是以下四种指令之一:(这里a表示一个正整数。)
1、+a:表示将当前的结果加上a;
2、-a:表示将当前的结果减去a;
3、*a:表示将当前的结果乘以a;
4、@a:表示将当前的结果加上a*X(X是一开始JYY输入的数)。
计算器用于记录运算结果的变量的存储范围是有限的,所以每次运算结束之
后会有计算结果溢出的问题。
JYY的计算器中,存储每计算结果的变量只能存储L到R之间的正整数,
如果一次指令执行过后,计算结果超过了R,那么计算器就会自动把结果变成R,然后再以R作为当前结果继续进行之后的计算。同理,如果运算结果小于L,计算器也会把结果变成L,再接着计算。
比如,假设计算器可以存储1到6之间的值,如果当前的计算结果是2,那
么在执行+5操作之后,存储结果的变量中的值将会是6。虽然2+5的实际结
果是7,但是由于7超过了存储范围的上界,所以结果就被自动更正成了上界的大小,也就是6。
JYY一共想在计算器上输入Q个值,他想知道这Q个值输入计算器之后,
分别会得到什么结果呢?

Input

输入文件的第一行包含三个正整数,N,L和R;

第接下来N行,每行一个指令,每个指令如题述,由一个字符和一个正整
数组成,字符和正整数中间有一个空格隔开;
第N+2行包含一个整数Q,表示JYY希望输入的数的数量;
第接下来Q行每行一个正整数,第k个正整数Xk表示JYY在第k次输入的
整数。

Output

输出Q行每行一个正整数,第k行的整数表示输入Xk后,依次经过N个指

令进行计算所得到的结果。

Sample Input

5 1 6
+ 5
- 3
* 2
- 7
@ 2
3
2
1
5

Sample Output

5
3
6

HINT

 【样例说明】


当JYY输入2时,计算器会进行5次运算,每一次运算之后得到的结果分

别是6(实际计算结果为7但是超过了上界),3,6,1(实际结果为-1但是低于了下界)和5(由于一开始输入的是2,所以这一次计算为1+2×2)。


1<=N,Q<=10^5,1<=L<=Xk<=R<=10^9,1<=a<=10^9

【其实也是JSOI2014 第二轮D2T3】

总觉得现在去省选现场还是做不出这种题目。

第一眼看到JYY和序列操作有关我就猜到是线段树。【题目很明显是数据结构,而这种操作几乎都是线段树】

关键是怎么来维护操作。

可以很明显地发现,所有操作均不改变数的相对大小【若x<y,则操作后x<=y】【现场做题时也就想到这里了】

所以我们可以排序。然后所有数一起操作。

不过这样肯定会超时的。我们又可以发现,所有会超过边界的一定是最左边一段或者最右边一段。

那么我们对于这一段可以直接区间赋值。对于一段内没有任何数超过边界的也可以区间进行操作

那么这个问题就解决了

【结果还是调了好久。代码还写的是最长】

----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

#include<cstdio>
#include<string>
#include<cstring>
#include<algorithm>
using namespace std;
struct tree
{
     int l,r;
     long long x,lx;
     long long m,lm;
     long long mi,lmi;
     long long tag;
     long long tag1,tag2,tag3;
}tr[800001];
struct number
{
     int x,t;
     bool operator <(number y) const
     {
          return x<y.x;
     }
}a[100001];
struct question
{
     int p,x;
}ask[100001];
int fx[100001];
int ll,rr;
inline void up(int p)
{
     tr[p].m=max(tr[p*2].m,tr[p*2+1].m);
     tr[p].lm=max(tr[p*2].lm,tr[p*2+1].lm);
     tr[p].mi=min(tr[p*2].mi,tr[p*2+1].mi);
     tr[p].lmi=min(tr[p*2].lmi,tr[p*2+1].lmi);
}
inline void down(int p)
{
	 if(tr[p].tag!=0)
	 {
          tr[p*2].m=tr[p].tag;
          tr[p*2+1].m=tr[p].tag;
          tr[p*2].mi=tr[p].tag;
          tr[p*2+1].mi=tr[p].tag;
          tr[p*2].tag2=1;
          tr[p*2].tag1=0;
          tr[p*2].tag3=0;
          tr[p*2+1].tag2=1;
          tr[p*2+1].tag1=0;
          tr[p*2+1].tag3=0;
          tr[p*2].tag=tr[p].tag;
          tr[p*2+1].tag=tr[p].tag;
          tr[p].tag=0;
	 }
     tr[p*2].m*=tr[p].tag2;
     tr[p*2].m+=tr[p].tag1;
     tr[p*2].m+=tr[p].tag3*tr[p*2].lm;
     
     tr[p*2+1].m*=tr[p].tag2;
     tr[p*2+1].m+=tr[p].tag1;
     tr[p*2+1].m+=tr[p].tag3*tr[p*2+1].lm;
     
     tr[p*2].mi*=tr[p].tag2;
     tr[p*2].mi+=tr[p].tag1;
     tr[p*2].mi+=tr[p].tag3*tr[p*2].lmi;
     
     tr[p*2+1].mi*=tr[p].tag2;
     tr[p*2+1].mi+=tr[p].tag1;
     tr[p*2+1].mi+=tr[p].tag3*tr[p*2+1].lmi;
     
     tr[p*2].tag2*=tr[p].tag2;
     tr[p*2].tag1=tr[p*2].tag1*tr[p].tag2+tr[p].tag1;
     tr[p*2].tag3=tr[p*2].tag3*tr[p].tag2+tr[p].tag3;
     
     tr[p*2+1].tag2*=tr[p].tag2;
     tr[p*2+1].tag1=tr[p*2+1].tag1*tr[p].tag2+tr[p].tag1;
     tr[p*2+1].tag3=tr[p*2+1].tag3*tr[p].tag2+tr[p].tag3;
     
     tr[p].tag2=1;
     tr[p].tag1=0;
     tr[p].tag3=0;
}
inline void build(int p,int l,int r)
{
     tr[p].l=l;
     tr[p].r=r;
     if(l!=r)
     {
          int mid=(l+r)/2;
          if(l<=mid)
               build(p*2,l,mid);
          if(r>mid)
               build(p*2+1,mid+1,r);
          up(p);
          tr[p].tag2=1;
     }
     else
     {
     	  tr[p].lx=a[l].x;
          tr[p].x=a[l].x;
          tr[p].lm=a[l].x;
          tr[p].m=a[l].x;
          tr[p].lmi=a[l].x;
          tr[p].mi=a[l].x;
          tr[p].tag2=1;
     }
}
inline void add(int p,int l,int r,long long x)
{
     if(l<=tr[p].l&&tr[p].r<=r)
     {
     	  down(p);
          if(tr[p].m+x<=rr&&tr[p].mi+x>=ll)
          {
               tr[p].tag1+=x;
               tr[p].m+=x;
               tr[p].mi+=x;
          }
          else if(tr[p].mi+x>=rr)
          {
          	   tr[p].m=rr;
          	   tr[p].mi=rr;
               tr[p].tag2=1;
               tr[p].tag1=0;
               tr[p].tag3=0;
               tr[p].tag=rr;
          }
          else if(tr[p].m+x<=ll)
          {
          	   tr[p].m=ll;
          	   tr[p].mi=ll;
               tr[p].tag2=1;
               tr[p].tag1=0;
               tr[p].tag3=0;
               tr[p].tag=ll;
          }
          else if(tr[p].l==tr[p].r)
          {
               tr[p].m+=x;
               if(tr[p].m<ll)
                    tr[p].m=ll;
               if(tr[p].m>rr)
                    tr[p].m=rr;
               tr[p].mi=tr[p].m;
               tr[p].tag1+=x;
               if(tr[p].tag1<ll)
                    tr[p].tag1=ll;
               if(tr[p].tag1>rr)
                    tr[p].tag1=rr;
          }
          else
          {
               int mid=(tr[p].l+tr[p].r)/2;
               if(l<=mid)
                    add(p*2,l,r,x);
               if(r>mid)
                    add(p*2+1,l,r,x);
               up(p);
          }
     }
     else
     {
     	  down(p);
          int mid=(tr[p].l+tr[p].r)/2;
          if(l<=mid)
               add(p*2,l,r,x);
          if(r>mid)
               add(p*2+1,l,r,x);
          up(p);
     }
}
inline void exadd(int p,int l,int r,long long x)
{
     if(l<=tr[p].l&&tr[p].r<=r)
     {
     	  down(p);
          if(tr[p].m*x<=rr)
          {
          	   down(p);
               tr[p].tag2*=x;
               tr[p].m*=x;
               tr[p].mi*=x;
          }
          else if(tr[p].mi*x>=rr)
          {
          	   tr[p].m=rr;
          	   tr[p].mi=rr;
               tr[p].tag2=1;
               tr[p].tag1=0;
               tr[p].tag3=0;
               tr[p].tag=rr;
          }
          else if(tr[p].l==tr[p].r)
          {
               tr[p].m*=x;
               if(tr[p].m<ll)
                    tr[p].m=ll;
               if(tr[p].m>rr)
                    tr[p].m=rr;
               tr[p].mi=tr[p].m;
               tr[p].tag2*=x;
               if(tr[p].tag2>rr)
                    tr[p].tag2=rr;
          }
          else
          {
               int mid=(tr[p].l+tr[p].r)/2;
               if(l<=mid)
                    exadd(p*2,l,r,x);
               if(r>mid)
                    exadd(p*2+1,l,r,x);
               up(p);
          }
     }
     else
     {
     	  down(p);
          int mid=(tr[p].l+tr[p].r)/2;
          if(l<=mid)
               exadd(p*2,l,r,x);
          if(r>mid)
               exadd(p*2+1,l,r,x);
          up(p);
     }
}
inline void change(int p,int l,int r,long long x)
{
     if(l<=tr[p].l&&tr[p].r<=r)
     {
     	  down(p);
          if(tr[p].m+tr[p].lm*x<=rr)
          {
               tr[p].tag3+=x;
               tr[p].m+=tr[p].lm*x;
               tr[p].mi+=tr[p].lmi*x;
          }
          else if(tr[p].mi+tr[p].lmi*x>=rr)
          {
          	   tr[p].m=rr;
          	   tr[p].mi=rr;
               tr[p].tag2=1;
               tr[p].tag1=0;
               tr[p].tag3=0;
               tr[p].tag=rr;
          }
          else if(tr[p].l==tr[p].r)
          {
               tr[p].m+=tr[p].lm*x;
               if(tr[p].m<ll)
                    tr[p].m=ll;
               if(tr[p].m>rr)
                    tr[p].m=rr;
               tr[p].mi=tr[p].m;
               tr[p].tag3+=x;
               if(tr[p].tag3>rr)
                    tr[p].tag3=rr;
          }
          else
          {
               int mid=(tr[p].l+tr[p].r)/2;
               if(l<=mid)
                    change(p*2,l,r,x);
               if(r>mid)
                    change(p*2+1,l,r,x);
               up(p);
          }
     }
     else
     {
     	  down(p);
          int mid=(tr[p].l+tr[p].r)/2;
          if(l<=mid)
               change(p*2,l,r,x);
          if(r>mid)
               change(p*2+1,l,r,x);
          up(p);
     }
}
inline long long find(int p,int l,int r)
{
     if(tr[p].l==l&&tr[p].r==r)
          return tr[p].m;
     else
     {
          down(p);
          int mid=(tr[p].l+tr[p].r)/2;
          if(l<=mid)
               return find(p*2,l,r);
          if(r>mid)
               return find(p*2+1,l,r);
     }
}
int main()
{
     int n;
     scanf("%d%d%d",&n,&ll,&rr);
     int i;
     char x[10];
     for(i=1;i<=n;i++)
     {
          scanf("%s",x);
          if(x[0]=='+')
               ask[i].p=1;
          else if(x[0]=='-')
               ask[i].p=2;
          else if(x[0]=='*')
               ask[i].p=3;
          else if(x[0]=='@')
               ask[i].p=4;
          scanf("%d",&ask[i].x);
     }
     int q;
     scanf("%d",&q);
     for(i=1;i<=q;i++)
     {
          scanf("%d",&a[i].x);
          a[i].t=i;
     }
     sort(a+1,a+1+q);
     for(i=1;i<=q;i++)
          fx[a[i].t]=i;
     build(1,1,q);
     for(i=1;i<=n;i++)
     {
     	  /*for(int j=1;j<=5;j++)
     	       printf("%d %d %lld %lld %lld %lld\n",tr[j].l,tr[j].r,tr[j].m,tr[j].mi,tr[j].tag,tr[j].tag1);
     	  printf("\n");*/
          if(ask[i].p==1)
               add(1,1,q,ask[i].x);
          else if(ask[i].p==2)
               add(1,1,q,-ask[i].x);
          else if(ask[i].p==3)
               exadd(1,1,q,ask[i].x);
          else if(ask[i].p==4)
               change(1,1,q,ask[i].x);
     }
     	/*  for(int j=1;j<=5;j++)
     	       printf("%d %d %lld %lld %lld %lld\n",tr[j].l,tr[j].r,tr[j].m,tr[j].mi,tr[j].tag,tr[j].tag1);*/
     for(i=1;i<=q;i++)
          printf("%lld\n",find(1,fx[i],fx[i]));
     return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值