BZOJ 3878 [AHOI&JSOI2014]奇怪的计算器 (线段树)
线段树好题
题目保证$a$一定是正整数,容易发现计算结果是单调的
我们把询问离线,并按照从小到大排序
某次操作可能导致某些位置达到边界$L/R$
根据单调性的结论
这些位置一定是从$1$向右扩展或者$Q$向左扩展
可以二分找到这个区间,然后区间覆盖
那么修改操作,归根结底是这$4$种操作:
1.区间加减 2.区间乘法 3.区间覆盖 4.区间每个位置加某个数*对应位置的固定权值
比较复杂,考虑抽象化这个问题,把它写成一个函数
$f(a,b,c)=a*f(a,b,c)+b*X_{i}+c$
上述四种操作变成
$1.f(1,0,x) 2.(x,0,0) 3.(0,0,x) 4.(1,x,0)$
我们只需要每次把值往里面带,然后用线段树维护这个函数就行了
注意下推标记的顺序
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 #define N1 100010 5 #define ll long long 6 using namespace std; 7 8 9 int gint() 10 { 11 int ret=0,fh=1; char c=getchar(); 12 while(c<'0'||c>'9'){if(c=='-')fh=-1;c=getchar();} 13 while(c>='0'&&c<='9'){ret=ret*10+c-'0';c=getchar();} 14 return ret*fh; 15 } 16 17 int n; 18 ll ml,mr; 19 struct node{int id,x;ll ans;}q[N1]; 20 int cmp1(node s1,node s2){return s1.x<s2.x;} 21 int cmp2(node s1,node s2){return s1.id<s2.id;} 22 int v[N1],p[N1],f[N1],m; 23 24 struct SEG{ 25 #define M1 (N1<<2) 26 ll mi[M1],ma[M1],a[M1],b[M1],c[M1]; 27 void pushup(int rt) 28 { 29 mi[rt]=mi[rt<<1]; 30 ma[rt]=ma[rt<<1|1]; 31 } 32 void pushdown(int l,int r,int rt) 33 { 34 int mid=(l+r)>>1; 35 if(a[rt]==1&&!b[rt]&&!c[rt]) return; 36 a[rt<<1]=a[rt]*a[rt<<1]; 37 a[rt<<1|1]=a[rt]*a[rt<<1|1]; 38 b[rt<<1]=a[rt]*b[rt<<1]+b[rt]; 39 b[rt<<1|1]=a[rt]*b[rt<<1|1]+b[rt]; 40 c[rt<<1]=a[rt]*c[rt<<1]+c[rt]; 41 c[rt<<1|1]=a[rt]*c[rt<<1|1]+c[rt]; 42 mi[rt<<1]=a[rt]*mi[rt<<1]+b[rt]*v[l]+c[rt]; 43 mi[rt<<1|1]=a[rt]*mi[rt<<1|1]+b[rt]*v[mid+1]+c[rt]; 44 ma[rt<<1]=a[rt]*ma[rt<<1]+b[rt]*v[mid]+c[rt]; 45 ma[rt<<1|1]=a[rt]*ma[rt<<1|1]+b[rt]*v[r]+c[rt]; 46 a[rt]=1; b[rt]=c[rt]=0; 47 } 48 void update(int L,int R,int l,int r,int rt,ll A,ll B,ll C) 49 { 50 if(L<=l&&r<=R) 51 { 52 a[rt]=A*a[rt]; 53 b[rt]=A*b[rt]+B; 54 c[rt]=A*c[rt]+C; 55 mi[rt]=A*mi[rt]+B*v[l]+C; 56 ma[rt]=A*ma[rt]+B*v[r]+C; 57 return; 58 } 59 int mid=(l+r)>>1; 60 if(L<=mid) update(L,R,l,mid,rt<<1,A,B,C); 61 if(R>mid) update(L,R,mid+1,r,rt<<1|1,A,B,C); 62 pushup(rt); 63 64 } 65 ll calc1(int x,ll rt,ll A,ll B,ll C){return A*mi[rt]+B*v[x]+C;} 66 ll calc2(int x,ll rt,ll A,ll B,ll C){return A*ma[rt]+B*v[x]+C;} 67 ll de; 68 int qleft(int l,int r,int rt,int A,int B,int C) 69 { 70 if(l==r){ if(calc2(r,rt,A,B,C)>ml) return l-1; return l; } 71 int mid=(l+r)>>1; pushdown(l,r,rt); de=calc2(mid,rt<<1,A,B,C); 72 if(calc2(mid,rt<<1,A,B,C)<=ml) return qleft(mid+1,r,rt<<1|1,A,B,C); 73 else return qleft(l,mid,rt<<1,A,B,C); 74 } 75 int qright(int l,int r,int rt,int A,int B,int C) 76 { 77 if(l==r){ if(calc1(l,rt,A,B,C)<mr) return l+1; return l; } 78 int mid=(l+r)>>1; pushdown(l,r,rt); de=calc1(mid+1,rt<<1|1,A,B,C); 79 if(calc1(mid+1,rt<<1|1,A,B,C)>=mr) return qright(l,mid,rt<<1,A,B,C); 80 else return qright(mid+1,r,rt<<1|1,A,B,C); 81 } 82 void build(int l,int r,int rt) 83 { 84 a[rt]=1; b[rt]=c[rt]=0; 85 if(l==r){ mi[rt]=ma[rt]=v[l]; return; } 86 int mid=(l+r)>>1; 87 build(l,mid,rt<<1); 88 build(mid+1,r,rt<<1|1); 89 pushup(rt); 90 } 91 void print(int l,int r,int rt,node *s) 92 { 93 if(l==r){ s[l].ans=mi[rt]; return; } 94 int mid=(l+r)>>1; pushdown(l,r,rt); 95 print(l,mid,rt<<1,s); 96 print(mid+1,r,rt<<1|1,s); 97 } 98 ll query(int x,int l,int r,int rt) 99 { 100 if(l==r) return mi[rt]; 101 int mid=(l+r)>>1; pushdown(l,r,rt); 102 if(x<=mid) return query(x,l,mid,rt<<1); 103 else return query(x,mid+1,r,rt<<1|1); 104 } 105 }s; 106 107 108 int main() 109 { 110 scanf("%d%lld%lld",&n,&ml,&mr); 111 char str[10]; int i,j,l,r; 112 for(i=1;i<=n;i++) 113 { 114 scanf("%s",str); 115 switch(str[0]) 116 { 117 case '+': p[i]=1; break; 118 case '-': p[i]=2; break; 119 case '*': p[i]=3; break; 120 case '@': p[i]=4; break; 121 } 122 f[i]=gint(); 123 } 124 scanf("%d",&m); 125 for(i=1;i<=m;i++) q[i].x=gint(),q[i].id=i; 126 sort(q+1,q+m+1,cmp1); 127 for(i=1;i<=m;i++) v[i]=q[i].x; 128 s.build(1,m,1); 129 s.query(1,1,m,1); 130 for(i=1;i<=n;i++) 131 { 132 switch(p[i]) 133 { 134 135 case 1: 136 { 137 l=s.qright(1,m,1,1,0,f[i]),r=m; 138 if(l>1) s.update(1,l-1,1,m,1,1,0,f[i]); 139 if(l<=r) s.update(l,r,1,m,1,0,0,mr); 140 break; 141 } 142 case 2: 143 { 144 l=s.qleft(1,m,1,1,0,-f[i]),r=m; 145 if(l>0) s.update(1,l,1,m,1,0,0,ml); 146 if(l<r) s.update(l+1,r,1,m,1,1,0,-f[i]); 147 break; 148 } 149 case 3: 150 { 151 l=s.qright(1,m,1,f[i],0,0),r=m; 152 if(l>1) s.update(1,l-1,1,m,1,f[i],0,0); 153 if(l<=r) s.update(l,r,1,m,1,0,0,mr); 154 break; 155 } 156 case 4: 157 { 158 l=s.qright(1,m,1,1,f[i],0),r=m; 159 if(l>1) s.update(1,l-1,1,m,1,1,f[i],0); 160 if(l<=r) s.update(l,r,1,m,1,0,0,mr); 161 break; 162 } 163 164 } 165 166 } 167 s.print(1,m,1,q); 168 sort(q+1,q+m+1,cmp2); 169 for(i=1;i<=m;i++) printf("%lld\n",q[i].ans); 170 return 0; 171 }