Problem 1464 - Deal with numbers
Time Limit: 5000MS Memory Limit: 65536KB
Total Submit: 209 Accepted: 21 Special Judge: No
Description
There are n numbers with the corresponding NO.1-n, and the value of the i-th number is xi.
Define three operations:
1.Division a b c, in the interval [a,b], if the value of a number is equal or greater than zero, then its value changed to it divide C(integer division). (1 <= a <= b <= n, 1 <= c <= 50000)
2.Minus a b c, all numbers in the interval [a, b] subtract c. (1 <= a <= b <= n ,1<= c <= 50000)
3.Sum a b, query for the sum of all numbers in the interval [a, b]. (1 <= a <= b <= n)
Input
Input contains several test cases.
The first line is an integer T indicates the number of test cases.
For each test case, the first line contains two integer numbers n and m (1<=n,m<=10^5), indicates the number of numbers and the number of operations. The second line contains n integers, the i-th integer shows the original value of the i-th number (1<=xi<=50000). Then m lines followed, each line shows an operation.
Output
For each set of data, output the case number in a line first, and then for each query, output an integer in a line to show the answer.
Print a blank line after the end of each test cases.
Sample Input
2
5 5
1 2 3 4 5
Division 1 3 2
Minus 3 5 3
Sum 1 2
Sum 3 4
Sum 5 5
5 3
-2 -1 3 -2 1
Sum 1 2
Division 1 2 2
Sum 1 2
Sample Output
Case 1:
1
-1
2
Case 2:
-3
-3
#include<cstdio>
#include<cstring>
using namespace std;
#define N 100005
#define ll long long
ll left[4*N],right[4*N];
ll sum[4*N],add[4*N];
bool f[4*N];
inline void push_up(ll k)
{
sum[k]=sum[2*k]+sum[2*k+1];
f[k]=f[2*k]&&f[2*k+1];
}
void push_down(ll k,ll l)
{
if(add[k]!=0)
{
add[2*k]+=add[k];add[2*k+1]+=add[k];
sum[2*k]+=add[k]*(l-l/2);sum[2*k+1]+=add[k]*(l/2);
add[k]=0;
}
}
void build(ll l,ll r,ll k)
{
add[k]=sum[k]=0;
left[k]=l;
right[k]=r;
if(l==r)
{
scanf("%lld",&sum[k]);
f[k]=(sum[k]<0);
return ;
}
ll mid=(l+r)>>1;
build(l,mid,2*k);
build(mid+1,r,2*k+1);
push_up(k);
}
ll l,r,c;
void div(ll k)
{
if(f[k])return;
if(left[k]==right[k])
{
if(sum[k]>=0&&c)sum[k]/=c;
f[k]=sum[k]<0;
return ;
}
push_down(k,right[k]-left[k]+1);
ll mid=(left[k]+right[k])>>1;
if(l<=mid)div(2*k);
if(r>mid)div(2*k+1);
push_up(k);
}
void ADD(ll k)
{
if(l<=left[k]&&right[k]<=r)
{
add[k]+=c;
sum[k]+=c*(right[k]-left[k]+1);
return ;
}
push_down(k,right[k]-left[k]+1);
ll mid=(left[k]+right[k])>>1;
if(l<=mid)ADD(2*k);
if(r>mid)ADD(2*k+1);
push_up(k);
}
ll SUM(ll k)
{
if(l<=left[k]&&right[k]<=r)
{
return sum[k];
}
push_down(k,right[k]-left[k]+1);
ll mid=(left[k]+right[k])>>1;
ll ans=0;
if(l<=mid)ans+=SUM(2*k);
if(r>mid)ans+=SUM(2*k+1);
return ans;
}
int main()
{
//freopen("C:\\Users\\Administrator\\Desktop\\in.txt","r",stdin);
freopen("G:\\新建文件夹\\D\\D.in","r",stdin);
freopen("G:\\新建文件夹\\D\\ddd.out","w",stdout);
ll n,m,t;
char s[20];
scanf("%lld",&t);
{
int k=0;
while(~scanf("%lld%lld",&n,&m))
{
printf("Case %d:\n",++k);
build(1,n,1);
while(m--)
{
scanf("%s%lld%lld",s,&l,&r);
if(s[0]=='S')
{
printf("%lld\n",SUM(1));
}
else
{
scanf("%lld",&c);
if(s[0]=='D')
{
if(c!=1)div(1);//没有这个优化过不了
}
else if(s[0]=='M')
{
c=-c;
ADD(1);
}
}
}
puts("");
}
}
return 0;
}