http://acm.whu.edu.cn/land/problem/detail?problem_id=1464
题目:
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)
思路:
线段树,对减法,直接用常规方法,除法暴力算,用flag标记下区间,下次可能就不这个区间就不用算了;
代码:
View Code
#include <cstdio> #define N 100005 typedef long long LL; struct st { LL x,y,flag,sum,add; }p[N * 5]; LL a[N]; void build(LL r,LL x,LL y) { p[r].x = x; p[r].y = y; p[r].add = 0; if(x == y) { p[r].sum = a[x]; if(a[x] > 0) p[r].flag = 1; else p[r].flag = 0; return ; } LL mid = (x + y) >> 1,tem = r * 2; build(tem,x,mid); build(tem + 1,mid + 1,y); p[r].sum = p[tem].sum + p[tem + 1].sum; if(p[tem].flag || p[tem + 1].flag) p[r].flag = 1; else p[r].flag = 0; } void dd(LL r,LL x,LL y,LL d) { if(!p[r].flag) return ; if(p[r].x == x && p[r].y == y && x == y) { if(p[r].sum > 0) { p[r].sum = p[r].sum / d; if(p[r].sum > 0) p[r].flag = 1; else p[r].flag = 0; } else p[r].flag = 0; return ; } LL mid = (p[r].x + p[r].y) >> 1,tem = r * 2; if(p[r].add) { p[tem].sum += (p[tem].y - p[tem].x + 1) * p[r].add; p[tem].add += p[r].add; p[tem + 1].sum += (p[tem + 1].y - p[tem + 1].x + 1) * p[r].add; p[tem + 1].add += p[r].add; p[r].add = 0; } if(y <= mid) dd(tem,x,y,d); else if(x > mid) dd(tem + 1,x,y,d); else { dd(tem,x,mid,d); dd(tem + 1,mid + 1,y,d); } if(p[tem].flag || p[tem + 1].flag) p[r].flag = 1; else p[r].flag = 0; p[r].sum = p[tem].sum + p[tem + 1].sum; } void insert(LL r,LL x,LL y,LL add) { if(p[r].x == x && p[r].y == y) { p[r].sum += (y - x + 1) * add; p[r].add += add; return ; } LL mid = (p[r].x + p[r].y) >> 1,tem = r * 2; if(p[r].add) { p[tem].sum += (p[tem].y - p[tem].x + 1) * p[r].add; p[tem].add += p[r].add; p[tem + 1].sum += (p[tem + 1].y - p[tem + 1].x + 1) * p[r].add; p[tem + 1].add += p[r].add; p[r].add = 0; } if(y <= mid) insert(tem,x,y,add); else if(x > mid) insert(tem + 1,x,y,add); else { insert(tem,x,mid,add); insert(tem + 1,mid + 1,y,add); } p[r].sum = p[tem].sum + p[tem + 1].sum; } LL query(LL r,LL x,LL y) { LL sum = 0; if(p[r].x == x && p[r].y == y) { return p[r].sum; } LL mid = (p[r].x + p[r].y) >> 1,tem = r * 2; if(p[r].add) { p[tem].sum += (p[tem].y - p[tem].x + 1) * p[r].add; p[tem].add += p[r].add; p[tem + 1].sum += (p[tem + 1].y - p[tem + 1].x + 1) * p[r].add; p[tem + 1].add += p[r].add; p[r].add = 0; } if(y <= mid) sum += query(tem,x,y); else if(x > mid) sum += query(tem + 1,x,y); else sum = sum + query(tem,x,mid) + query(tem + 1,mid + 1,y); return sum; } int main() { LL t,u = 0; scanf("%lld",&t); while(t --) { LL n,m; scanf("%lld %lld",&n,&m); for(LL i = 1;i <= n;i ++) scanf("%lld",&a[i]); build(1,1,n); char ch[10]; LL x,y,z; printf("Case %lld:\n",++ u); while(m --) { scanf("%s",ch); if(ch[0] == 'D') { scanf("%lld %lld %lld",&x,&y,&z); if(z > 1) dd(1,x,y,z); } else if(ch[0] == 'M') { scanf("%lld %lld %lld",&x,&y,&z); insert(1,x,y,-z); } else { scanf("%lld %lld",&x,&y); printf("%lld\n",query(1,x,y)); } } printf("\n"); } return 0; }