BZOJ 3878 Ahoi2014 strange calculator line segment tree
Given n operations, each operation has four forms. If R is changed to R. Now, q inputs are given and their output is obtained.
N, q <= 10 W
Create a line segment tree with the q number. All four operations can be performed on the Line Segment tree.
But what if overflow occurs?
It is easy to find that if x is <= y, x must be <= y
Because the four operations are linear, overflow does not reverse the relationship between the two numbers.
Then we can sort the q number in advance, so the overflow number must be modified in two consecutive intervals.
How to find the overflow interval between the two ends ...... Each node maintains the maximum and minimum values of an interval.
In addition, the data is still relatively conscientious and will not be exposed to long.
I have written the code four times in a simple way.-Before writing the code, you must be clear.-At least TM first-hand simulated samples. QAQ
#include
#include
#include
#include
#include #define M 100100using namespace std;int n,m,L,R;int q[M];long long a[M];struct Operation{int type,x;friend istream& operator >> (istream &_,Operation &o){char p[10];scanf("%s%d",p,&o.x);switch(p[0]){case '+':o.type=1;break;case '-':o.type=2;break;case '*':o.type=3;break;case '@':o.type=4;break;}return _;}}operations[M];struct Segtree{Segtree *ls,*rs;long long times_mark,k,b;long long min_num,max_num;Segtree():ls(0x0),rs(0x0),times_mark(1),k(0),b(0) {}void Build_Tree(int x,int y){int mid=x+y>>1;min_num=a[x];max_num=a[y];if(x==y) return ;(ls=new Segtree)->Build_Tree(x,mid);(rs=new Segtree)->Build_Tree(mid+1,y);}void Get_Mark(int x,int y,long long _,long long __,long long ___){min_num=_*min_num+__*a[x]+___;max_num=_*max_num+__*a[y]+___;times_mark*=_;k*=_;b*=_;k+=__;b+=___;}void Push_Down(int x,int y){int mid=x+y>>1;ls->Get_Mark(x,mid,times_mark,k,b);rs->Get_Mark(mid+1,y,times_mark,k,b);times_mark=1;k=b=0;}int Get_Ans(int x,int y,int pos){int mid=x+y>>1;if(x==y) return max_num;Push_Down(x,y);if(pos<=mid)return ls->Get_Ans(x,mid,pos);elsereturn rs->Get_Ans(mid+1,y,pos);}void Get_L(int x,int y){int mid=x+y>>1;if(x==y){Get_Mark(x,y,0,0,L);return ;}Push_Down(x,y);if(rs->min_num
Get_Mark(x,mid,0,0,L),rs->Get_L(mid+1,y);elsels->Get_L(x,mid);min_num=ls->min_num;max_num=rs->max_num;}void Get_R(int x,int y){int mid=x+y>>1;if(x==y){Get_Mark(x,y,0,0,R);return ;}Push_Down(x,y);if(ls->max_num>R)rs->Get_Mark(mid+1,y,0,0,R),ls->Get_R(x,mid);elsers->Get_R(mid+1,y);min_num=ls->min_num;max_num=rs->max_num;}}*tree=new Segtree;int main(){int i;cin>>n>>L>>R;for(i=1;i<=n;i++)cin>>operations[i];cin>>m;for(i=1;i<=m;i++)scanf("%d",&q[i]),a[i]=q[i];sort(a+1,a+m+1);tree->Build_Tree(1,m);for(i=1;i<=n;i++){switch(operations[i].type){case 1:tree->Get_Mark(1,m,1,0,operations[i].x);break;case 2:tree->Get_Mark(1,m,1,0,-operations[i].x);break;case 3:tree->Get_Mark(1,m,operations[i].x,0,0);break;case 4:tree->Get_Mark(1,m,1,operations[i].x,0);break;}if(tree->min_num
Get_L(1,m);if(tree->max_num>R)tree->Get_R(1,m);}for(i=1;i<=m;i++){int pos=lower_bound(a+1,a+m+1,q[i])-a;printf("%d\n",tree->Get_Ans(1,m,pos) );}return 0;}