1. 程式人生 > >BZOJ 3878 [AHOI&JSOI2014]奇怪的計算器 (線段樹)

BZOJ 3878 [AHOI&JSOI2014]奇怪的計算器 (線段樹)

scan long long http d+ left etc getchar() main line

題面:BZOJ傳送門 洛谷傳送門

線段樹好題

題目保證$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 }

BZOJ 3878 [AHOI&JSOI2014]奇怪的計算器 (線段樹)