whu 1464 deal with numbers

时间:2022-07-18 19:46:34

WHU 1464  deal with numbers

题意:

给你一串数字,对着串数字有三项操作:

Minus a,b,c:对区间[a,b]总的每个数都减c。

Division a,b,c:对区间[a,b]中的每个数都除以c。

Sum a,b:求出区间[a,b]的和~

由于该题是对区间里的所有数进行操作,用一般的线段树会TLE,在这里要用到Lazy_Tag。然后另外要注意的是除法如何维护:这里的数C <= 5*1E5 , 因为大于0才除,所以每个数最多被除 log(Ai) 次, N个数则最多被除 N*log(Ai) 次了。所以做除法可以直接更新到底,还有就是使用一个标记,区间中都不可被除时,就没必要更新到底了。另外,除数是1的时候,不能除,貌似后台数据好多1,~\(≧▽≦)/~

代码【来自:http://www.cnblogs.com/yefeng1627/archive/2013/04/15/3021460.html】:

 #include<cstdio>
#include<cstdlib>
#include<cstdlib>
#include<algorithm>
using namespace std; typedef long long LL;
const int N = 5e5+;
#define lch rt<<1,l,m
#define rch rt<<1|1,m+1,r
LL sum[N<<], add[N<<];
bool flag[N<<]; void push_up(int rt){
sum[rt]=sum[rt<<]+sum[rt<<|];
flag[rt]=flag[rt<<] | flag[rt<<|];
} void push_down(int rt,int L){
if( add[rt] ){
add[rt<<]+=add[rt];
add[rt<<|]+=add[rt];
sum[rt<<]+=(L-(L>>))*add[rt];
sum[rt<<|]+=(L>>)*add[rt];
add[rt]=;
}
} void build(int rt,int l,int r){
sum[rt] = add[rt] = ;
if(l == r){ scanf("%lld",&sum[rt]); flag[rt] = (sum[rt]>); return; }
int m = (l+r)>>;
build(lch), build(rch);
push_up(rt);
} void Minus(int rt,int l,int r,int a,int b,int c){
if(a <= l && r <= b){
add[rt] += c; sum[rt] += (r-l+)*c; return;
}
push_down(rt,r-l+);
int m = (l+r)>>;
if( a <= m ) Minus( lch,a,b,c );
if( m < b ) Minus( rch,a,b,c );
push_up(rt);
} void Division(int rt,int l,int r,int a,int b,int c){
if( flag[rt] == ) return;
if(l == r){
if(sum[rt]>) sum[rt] /= (LL)c;
flag[rt] = (sum[rt] > ); return;
}
push_down(rt, r-l+);
int m = (l+r)>>;
if( a <= m ) Division( lch,a,b,c );
if( m < b ) Division( rch,a,b,c );
push_up(rt);
} LL Sum(int rt,int l,int r,int a,int b){
if(a<=l && r<=b) return sum[rt];
push_down(rt,r-l+);
int m=(l+r)>>;
LL res=;
if(a<=m) res+=Sum(lch,a,b);
if(m<b) res+=Sum(rch,a,b);
return res;
} int main(){
int T;
scanf("%d", &T);
for(int Case = ; Case <= T; Case++){
int n, m, a, b, c;
char op[];
scanf("%d%d", &n,&m);
printf("Case %d:\n",Case);
build( , , n );
for(int i = ; i < m; i++){
scanf("%s", op);
if( op[] == 'D' ){
scanf("%d%d%d",&a,&b,&c);
if( c == ) continue;
Division(,,n,a,b,c);
}
else if( op[] == 'M' ){
scanf("%d%d%d",&a,&b,&c);
Minus(,,n,a,b,-c);
}
else{
scanf("%d%d",&a,&b);
LL res = Sum(,,n,a,b);
printf("%lld\n",res);
}
}
puts("");
}
return ;
}