HDU 5828 Rikka with Sequence
2016-08-11 21:02
513 查看
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
. 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
1
5 5
1 2 3 4 5
1 3 5 2
2 1 4
3 2 4
2 3 5
3 1 5
Sample Output
5
6
线段树的暴力更新,可以想象,sqrt操作的下降速度是很快的于是每个节点维护最大和最小值,当sqrt操作是暴力的传递下去,当最大值和最小值的sqrt相同时就无需下传了。
hdu上的数据已经加强了,上述版本会tle。对于加强的数据,之所以超时的原因是数据中出现了sqrt以后仍旧不相等的情况,举个例子,x和x+1,每次加上x^2+x,之后再开方,会保持原来的序列不变,这导致了暴力更新每次是真的暴力。解决这种情况的办法就是再多考虑极差为1的情况,可以想象,对于一段区间连续的加操作和开放操作,值之间的差一定会趋向于0或1,而不会是更大的数。所以在原来的情况下加上判断极差为1的情况,此时的开方操作相当于区间减操作。因为开方前相差1,开方后仍旧是相差1,这样就可以通过加强的数据了。
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
. 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
1
5 5
1 2 3 4 5
1 3 5 2
2 1 4
3 2 4
2 3 5
3 1 5
Sample Output
5
6
线段树的暴力更新,可以想象,sqrt操作的下降速度是很快的于是每个节点维护最大和最小值,当sqrt操作是暴力的传递下去,当最大值和最小值的sqrt相同时就无需下传了。
#include<set> #include<map> #include<ctime> #include<cmath> #include<stack> #include<queue> #include<bitset> #include<cstdio> #include<string> #include<cstring> #include<iostream> #include<algorithm> #include<functional> #define rep(i,j,k) for (int i = j; i <= k; i++) #define per(i,j,k) for (int i = j; i >= k; i--) #define lson x << 1, l, mid #define rson x << 1 | 1, mid + 1, r #define fi first #define se second #define mp(i,j) make_pair(i,j) #define pii pair<int,int> using namespace std; typedef long long LL; const int low(int x) { return x&-x; } const double eps = 1e-8; const int INF = 0x7FFFFFFF; const int mod = 1e9 + 7; const int N = 4e5 + 10; const int read() { char ch = getchar(); while (ch<'0' || ch>'9') ch = getchar(); int x = ch - '0'; while ((ch = getchar()) >= '0'&&ch <= '9') x = x * 10 + ch - '0'; return x; } int T, n, m, l, r, x, type; LL f , L , R , a ; int g(LL x) { return (int)sqrt(1.0*x); } void up(int x) { L[x] = min(L[x << 1], L[x << 1 | 1]); R[x] = max(R[x << 1], R[x << 1 | 1]); f[x] = f[x << 1] + f[x << 1 | 1]; } void build(int x, int l, int r) { a[x] = 0; if (l == r) { scanf("%d", &f[x]); R[x] = L[x] = f[x]; } else { int mid = l + r >> 1; build(lson); build(rson); up(x); } } void push(int x, int l, int r) { if (a[x]) { a[x << 1] += a[x]; L[x << 1] += a[x]; R[x << 1] += a[x]; f[x << 1] += 1LL * a[x] * ((l + r >> 1) - l + 1); a[x << 1 | 1] += a[x]; L[x << 1 | 1] += a[x]; R[x << 1 | 1] += a[x]; f[x << 1 | 1] += 1LL * a[x] * (r - (l + r >> 1)); a[x] = 0; } if (L[x] == R[x]) { a[x << 1] = a[x << 1 | 1] = 0; L[x << 1] = R[x << 1] = L[x << 1 | 1] = R[x << 1 | 1] = L[x]; f[x << 1] = 1LL * L[x] * ((l + r >> 1) - l + 1); f[x << 1 | 1] = 1LL * R[x] * (r - (l + r >> 1)); } } void add(int x, int l, int r, int ll, int rr, int v) { if (l < r && (a[x] || L[x] == R[x])) push(x, l, r); if (ll <= l && r <= rr) { a[x] += v; L[x] += v; R[x] += v; f[x] += 1LL * v * (r - l + 1); } else { int mid = l + r >> 1; if (ll <= mid) add(lson, ll, rr, v); if (rr > mid) add(rson, ll, rr, v); up(x); } } void down(int x, int l, int r, int ll, int rr) { if (l < r && (a[x] || L[x] == R[x])) push(x, l, r); if (ll <= l && r <= rr) { if (g(L[x]) == g(R[x])) { L[x] = R[x] = g(L[x]); f[x] = 1LL * L[x] * (r - l + 1); } else { int mid = l + r >> 1; if (ll <= mid) down(lson, ll, rr); if (rr > mid) down(rson, ll, rr); up(x); } } else { int mid = l + r >> 1; if (ll <= mid) down(lson, ll, rr); if (rr > mid) down(rson, ll, rr); up(x); } } LL sum(int x, int l, int r, int ll, int rr) { if (l < r && (a[x] || L[x] == R[x])) push(x, l, r); if (ll <= l && r <= rr) return f[x]; else { int mid = l + r >> 1; LL res = 0; if (ll <= mid) res += sum(lson, ll, rr); if (rr > mid) res += sum(rson, ll, rr); return res; } } int main() { T = read(); while (T--) { scanf("%d%d", &n, &m); build(1, 1, n); while (m--) { type = read(); l = read(); r = read(); if (type == 1) { x = read(); add(1, 1, n, l, r, x); } else { if (type == 2) down(1, 1, n, l, r); else printf("%lld\n", sum(1, 1, n, l, r)); } } } return 0; }
hdu上的数据已经加强了,上述版本会tle。对于加强的数据,之所以超时的原因是数据中出现了sqrt以后仍旧不相等的情况,举个例子,x和x+1,每次加上x^2+x,之后再开方,会保持原来的序列不变,这导致了暴力更新每次是真的暴力。解决这种情况的办法就是再多考虑极差为1的情况,可以想象,对于一段区间连续的加操作和开放操作,值之间的差一定会趋向于0或1,而不会是更大的数。所以在原来的情况下加上判断极差为1的情况,此时的开方操作相当于区间减操作。因为开方前相差1,开方后仍旧是相差1,这样就可以通过加强的数据了。
#include<set> #include<map> #include<ctime> #include<cmath> #include<stack> #include<queue> #include<bitset> #include<cstdio> #include<string> #include<cstring> #include<iostream> #include<algorithm> #include<functional> #define rep(i,j,k) for (int i = j; i <= k; i++) #define per(i,j,k) for (int i = j; i >= k; i--) #define lson x << 1, l, mid #define rson x << 1 | 1, mid + 1, r #define fi first #define se second #define mp(i,j) make_pair(i,j) #define pii pair<int,int> using namespace std; typedef long long LL; const int low(int x) { return x&-x; } const double eps = 1e-8; const int INF = 0x7FFFFFFF; const int mod = 1e9 + 7; const int N = 4e5 + 10; const int read() { char ch = getchar(); while (ch<'0' || ch>'9') ch = getchar(); int x = ch - '0'; while ((ch = getchar()) >= '0'&&ch <= '9') x = x * 10 + ch - '0'; return x; } int T, n, m, l, r, x, type; LL f , L , R , a ; int g(LL x) { return (int)sqrt(1.0*x); } void up(int x) { L[x] = min(L[x << 1], L[x << 1 | 1]); R[x] = max(R[x << 1], R[x << 1 | 1]); f[x] = f[x << 1] + f[x << 1 | 1]; } void build(int x, int l, int r) { a[x] = 0; if (l == r) { R[x] = L[x] = f[x] = read(); } else { int mid = l + r >> 1; build(lson); build(rson); up(x); } } void push(int x, int l, int r) { if (a[x]) { a[x << 1] += a[x]; L[x << 1] += a[x]; R[x << 1] += a[x]; f[x << 1] += 1LL * a[x] * ((l + r >> 1) - l + 1); a[x << 1 | 1] += a[x]; L[x << 1 | 1] += a[x]; R[x << 1 | 1] += a[x]; f[x << 1 | 1] += 1LL * a[x] * (r - (l + r >> 1)); } if (L[x] == R[x]) { L[x << 1] = R[x << 1] = L[x << 1 | 1] = R[x << 1 | 1] = L[x]; f[x << 1] = 1LL * L[x] * ((l + r >> 1) - l + 1); f[x << 1 | 1] = 1LL * R[x] * (r - (l + r >> 1)); } a[x] = 0; } void add(int x, int l, int r, int ll, int rr, int v) { if (l < r && (a[x] || L[x] == R[x])) push(x, l, r); if (ll <= l && r <= rr) { a[x] += v; L[x] += v; R[x] += v; f[x] += 1LL * v * (r - l + 1); } else { int mid = l + r >> 1; if (ll <= mid) add(lson, ll, rr, v); if (rr > mid) add(rson, ll, rr, v); up(x); } } void down(int x, int l, int r, int ll, int rr) { if (l < r && (a[x] || L[x] == R[x])) push(x, l, r); if (ll <= l && r <= rr) { if (g(L[x]) == g(R[x])) { L[x] = R[x] = g(L[x]); f[x] = 1LL * L[x] * (r - l + 1); } else if (L[x] + 1 == R[x]) { int k = R[x] - g(R[x]); add(x, l, r, ll, rr, -k); } else { int mid = l + r >> 1; if (ll <= mid) down(lson, ll, rr); if (rr > mid) down(rson, ll, rr); up(x); } } else { int mid = l + r >> 1; if (ll <= mid) down(lson, ll, rr); if (rr > mid) down(rson, ll, rr); up(x); } } LL sum(int x, int l, int r, int ll, int rr) { if (l < r && (a[x] || L[x] == R[x])) push(x, l, r); if (ll <= l && r <= rr) return f[x]; else { int mid = l + r >> 1; LL res = 0; if (ll <= mid) res += sum(lson, ll, rr); if (rr > mid) res += sum(rson, ll, rr); return res; } } int main() { T = read(); while (T--) { scanf("%d%d", &n, &m); build(1, 1, n); while (m--) { type = read(); l = read(); r = read(); if (type == 1) { x = read(); add(1, 1, n, l, r, x); } else { if (type == 2) down(1, 1, n, l, r); else printf("%lld\n", sum(1, 1, n, l, r)); } } } return 0; }
相关文章推荐
- HDU 5828 Rikka with Sequence(线段树+小优化)
- hdu 5828 Rikka with Sequence 【加强版已过】
- HDU 5828 Rikka with Sequence
- HDU 5828 Rikka with Sequence(线段树)
- HDU 5828-H - Rikka with Sequence-线段树+玄学-区间开方/区间更新/区间求和
- hdu 5828 2016 Multi-University Training Contest 8 Rikka with Sequence 解题报告
- Hdu-5828 Rikka with Sequence(线段树)
- HDU 5828 Rikka with Sequence (线段树)
- HDU 5828 多校第八场 1008 Rikka with Sequence(线段树--数据加强版)
- hdu 5828 Rikka with Sequence 线段树
- HDU 5828 Rikka with Sequence
- HDU-5828-Rikka with Sequence(线段树)
- HDU 5828 Rikka with Sequence(线段树 开根号)
- HDU 5828 Rikka with Sequence(线段树)
- HDU 5828 Rikka with Sequence 线段树优化
- HDU 5828 Rikka with Sequence 解题报告
- HDU 5828 Rikka with Sequence (线段树+剪枝优化)
- Hdu 5828 Rikka with Sequence
- hdu 5828 Rikka with Sequence 【线段树+优化】
- 2016多校8 HDU 5828 Rikka with Sequence 线段树优化