您的位置:首页 > 产品设计 > UI/UE

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相同时就无需下传了。
#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