HDU5828-Rikka with Sequence

来源:互联网 发布:中宏数据库 编辑:程序博客网 时间:2024/06/16 13:38

Rikka with Sequence

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


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 A[i]
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
 


题意: 区间有三种操作:区间加,区间开根和区间求和

解题思路:一开始我和大部分人一样是去判断一个区间里的数是不是全都一样,一样的话就可以区间更新,速度会比较快。不过据说后来数据加强了,数据中出现了sqrt以后仍旧不相等的情况,比如x和x+1,每次加上x^2+x,之后再开方,会保持原来的序列不变。解决这种情况的办法就是再多考虑极差为1的情况,区间值之间的差一定会趋向于0或1,而不会是更大的数。所以在原来的情况下加上判断极差为1的情况(判断区间最大值和最小值的差值即可),此时的开方操作相当于区间减操作,因为开方前相差1,开方后仍旧是相差1


#include <iostream>#include <cstdio>#include <cstring>#include <string>#include <algorithm>#include <cmath>#include <map>#include <cmath>#include <set>#include <stack>#include <queue>#include <vector>#include <bitset>#include <functional>using namespace std;#define LL long longconst int INF = 0x3f3f3f3f;int n, m, p, x, y;LL sum[100009 << 2], mi[100009 << 2], ma[100009 << 2], lazy[100009 << 2], z;void Merge(int k){mi[k] = min(mi[k << 1], mi[k << 1 | 1]);ma[k] = max(ma[k << 1], ma[k << 1 | 1]);sum[k] = sum[k << 1] + sum[k << 1 | 1];}void build(int k, int l, int r){lazy[k] = 0;if (l == r) { scanf("%lld", &sum[k]); ma[k] = mi[k] = sum[k]; return; }int mid = l + r >> 1;build(k << 1, l, mid), build(k << 1 | 1, mid + 1, r);Merge(k);}void Push(int k, int l, int r){int mid = (l + r) >> 1;if (lazy[k]){lazy[k << 1] += lazy[k]; mi[k << 1] += lazy[k]; ma[k << 1] += lazy[k];sum[k << 1] += lazy[k] * (mid - l + 1);lazy[k << 1 | 1] += lazy[k];    mi[k << 1 | 1] += lazy[k];    ma[k << 1 | 1] += lazy[k];sum[k << 1 | 1] += lazy[k] * (r - mid);}if (mi[k] == ma[k]){mi[k << 1] = ma[k << 1] = mi[k << 1 | 1] = ma[k << 1 | 1] = mi[k];sum[k << 1] = mi[k] * (mid - l + 1);sum[k << 1 | 1] = ma[k] * (r - mid);}lazy[k] = 0;}void update(int k, int l, int r, int ll, int rr, LL val){if (ll <= l && r <= rr){lazy[k] += val; mi[k] += val; ma[k] += val;sum[k] += val * (r - l + 1); return;}int mid = l + r >> 1;if (lazy[k] || mi[k] == ma[k]) Push(k, l, r);if (ll <= mid) update(k << 1, l, mid, ll, rr, val);if (rr > mid) update(k << 1 | 1, mid + 1, r, ll, rr, val);Merge(k);}void update(int k, int l, int r, int ll, int rr){if (ll <= l && r <= rr){if ((LL)sqrt(mi[k]) == (LL)sqrt(ma[k])){mi[k] = ma[k] = sqrt(ma[k]);sum[k] = mi[k] * (r - l + 1);}else if (mi[k] + 1 == ma[k]){LL kk = ma[k] - 1LL * sqrt(ma[k]);lazy[k] -= kk, ma[k] -= kk, mi[k] -= kk, sum[k] -= (r - l + 1)*kk;}else{int mid = l + r >> 1;if (lazy[k] || mi[k] == ma[k]) Push(k, l, r);if (ll <= mid) update(k << 1, l, mid, ll, rr);if (rr > mid) update(k << 1 | 1, mid + 1, r, ll, rr);Merge(k);}return;}int mid = l + r >> 1;if (lazy[k] || mi[k] == ma[k]) Push(k, l, r);if (ll <= mid) update(k << 1, l, mid, ll, rr);if (rr > mid) update(k << 1 | 1, mid + 1, r, ll, rr);Merge(k);}LL query(int k, int l, int r, int ll, int rr){if (ll <= l && r <= rr) return sum[k];int mid = l + r >> 1;if (lazy[k] || mi[k] == ma[k]) Push(k, l, r);LL ans = 0;if (ll <= mid) ans += query(k << 1, l, mid, ll, rr);if (rr > mid) ans += query(k << 1 | 1, mid + 1, r, ll, rr);return ans;}int main(){int t;scanf("%d", &t);while (t--){scanf("%d%d", &n, &m);build(1, 1, n);while (m--){scanf("%d%d%d", &p, &x, &y);if (p == 1){scanf("%lld", &z);update(1, 1, n, x, y, z);}else{if (p == 2) update(1, 1, n, x, y);else printf("%lld\n", query(1, 1, n, x, y));}}}return 0;}

原创粉丝点击