2016多校联赛7H (hdu5828) Rikka with Sequence

来源:互联网 发布:南京麦芽金服数据 编辑:程序博客网 时间:2024/06/04 19:00


Rikka with Sequence

Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 631    Accepted Submission(s): 183


Problem Description
As we know, Rikka is poor at math. Yuta is worrying about this situation, so he gives Rikka some math tasks to practice. There is one of them:

Yuta has an array A with n numbers. Then he makes m operations on it. 

There are three type of operations:

1 l r x : For each i in [l,r], change A[i] to A[i]+x
2 l r : For each i in [l,r], change A[i] to 
3 l r : Yuta wants Rikka to sum up A[i] for all i in [l,r]

It is too difficult for Rikka. Can you help her?
 

Input
The first line contains a number t(1<=t<=100), the number of the testcases. And there are no more than 5 testcases with n>1000.

For each testcase, the first line contains two numbers n,m(1<=n,m<=100000). The second line contains n numbers A[1]~A[n]. Then m lines follow, each line describe an operation.

It is guaranteed that 1<=A[i],x<=100000.
 

Output
For each operation of type 3, print a lines contains one number -- the answer of the query.
 

Sample Input
15 51 2 3 4 51 3 5 22 1 43 2 42 3 53 1 5
 

Sample Output
56
 

Author
学军中学
 

Source
2016 Multi-University Training Contest 8
 

Recommend
wange2014   |   We have carefully selected several similar problems for you:  5831 5830 5829 5827 5826 
题意:给你n个数,序列为1~n,三种操作,1是l~r之间的数全部加x,2是l~r之间的数全部开方,3求l~r之间的数的和。

思路:很明显这道题要用线段树,关键是怎么优化,操作1的优化估计大家都会,问题是操作2,第一种情况,一个数连续开方不超10次就会变成1,而1开方也还是1,那么我们只要判断区间里的数全部都是1就不用继续更新下去了,第二种情况,区间里的数全部相等,也就是区间的最大值等于最小值,那么开方之后的结果很容易就得出来了。下面给代码。

#include <map>  #include <set>  #include <cmath>  #include <queue>  #include <vector>  #include <cstdio>  #include <cstring>  #include <iostream>  #include <algorithm>  using namespace std;#define maxn 100005#define ll now<<1#define rr now<<1|1typedef long long LL;LL  sum[maxn << 2], minnum[maxn << 2], maxnum[maxn << 2], value[maxn << 2], addnum;void build(int l, int r, int now){if (l == r){scanf("%lld", &sum[now]);maxnum[now] = minnum[now] = sum[now];return;}int mid = (l + r) >> 1;build(l, mid, ll);build(mid + 1, r, rr);sum[now] = sum[ll] + sum[rr];minnum[now] = min(minnum[ll], minnum[rr]);maxnum[now] = max(maxnum[ll], maxnum[rr]);value[now] = 0;}void updateadd(int l1, int r1, int l2, int r2, int now){if (l2 <= l1&&r2 >= r1){sum[now] += addnum*(r1 - l1 + 1);maxnum[now] += addnum;minnum[now] += addnum;value[now] += addnum;return;}int mid = (l1 + r1) >> 1;if (value[now]){sum[ll] += (mid - l1 + 1)*value[now];sum[rr] += (r1 - mid)*value[now];maxnum[ll] += value[now];maxnum[rr] += value[now];minnum[ll] += value[now];minnum[rr] += value[now];value[ll] += value[now];value[rr] += value[now];value[now] = 0;}if (l2 <= mid)updateadd(l1, mid, l2, r2, ll);if (r2 > mid)updateadd(mid + 1, r1, l2, r2, rr);sum[now] = sum[ll] + sum[rr];maxnum[now] = max(maxnum[ll], maxnum[rr]);minnum[now] = min(minnum[ll], minnum[rr]);}void updatesqrt(int l1, int r1, int l2, int r2, int now){if (maxnum[now] == 1){return;}if (l2 <= l1&&r2 >= r1&&minnum[now] == maxnum[now]){LL temp = sqrt(maxnum[now]);sum[now] = (r1 - l1 + 1)*temp;value[now] -= maxnum[now] - temp;maxnum[now] = temp;minnum[now] = temp;return;}int mid = (l1 + r1) >> 1;if (value[now]){sum[ll] += (mid - l1 + 1)*value[now];sum[rr] += (r1 - mid)*value[now];maxnum[ll] += value[now];maxnum[rr] += value[now];minnum[ll] += value[now];minnum[rr] += value[now];value[ll] += value[now];value[rr] += value[now];value[now] = 0;}if (l2 <= mid)updatesqrt(l1, mid, l2, r2, ll);if (r2 > mid)updatesqrt(mid + 1, r1, l2, r2, rr);sum[now] = sum[ll] + sum[rr];maxnum[now] = max(maxnum[ll], maxnum[rr]);minnum[now] = min(minnum[ll], minnum[rr]);}LL query(int l1, int r1, int l2, int r2, int now){if (l2 <= l1&&r2 >= r1){return sum[now];}int mid = (l1 + r1) >> 1;if (value[now]){sum[ll] += (mid - l1 + 1)*value[now];sum[rr] += (r1 - mid)*value[now];maxnum[ll] += value[now];maxnum[rr] += value[now];minnum[ll] += value[now];minnum[rr] += value[now];value[ll] += value[now];value[rr] += value[now];value[now] = 0;}LL lsum = 0, rsum = 0;if (l2 <= mid)lsum = query(l1, mid, l2, r2, ll);if (r2 > mid)rsum = query(mid + 1, r1, l2, r2, rr);return lsum + rsum;}int main(){int t;scanf("%d", &t);while (t--){int n, m;scanf("%d%d", &n, &m);build(1, n, 1);while (m--){int cmd, l, r;scanf("%d%d%d", &cmd, &l, &r);if (cmd == 1){scanf("%lld", &addnum);updateadd(1, n, l, r, 1);}else if (cmd == 2){updatesqrt(1, n, l, r, 1);}else{printf("%lld\n", query(1, n, l, r, 1));}}}}


0 0
原创粉丝点击