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

Wow! Such Sequence!

2014-07-30 09:14 316 查看
题目链接

题意:

n个点,每个初始值为零,m个操作,共三种操作:
1 k d - "add"
2 l r - "query sum"
3 l r - "change to nearest Fibonacci"
1 ≤ n ≤ 100000, 1 ≤ m ≤ 100000, |d| < 231
分析:

首先,斐波那契增长速度很快,所以题目中的数可以直接递推求出来。

对于这个题目的区间更新操作,由于操作的特点,使得一直对一个数进行这个操作是多余的,所以记录一下当前区间如果进行了第三个操作是否会发生变化即可。
const int MAXN = 110000;

#define lson rt << 1
#define rson rt << 1 | 1

struct Node
{
int l, r, m;
LL sum;
int end;
} T[MAXN << 2];

LL fib[220];
void init()
{
fib[0] = fib[1] = 1;
REP(i, 200)
fib[i + 2] = fib[i] + fib[i + 1];
}
void trim(LL &n)
{
if (n == 0)
{
n = 1;
return;
}
int idx = lower_bound(fib, fib + 200, n) - fib;
if (fib[idx] != n)
n = n - fib[idx - 1] <= fib[idx] - n ? fib[idx - 1] : fib[idx];
}

void pushup(int rt)
{
T[rt].sum = T[lson].sum + T[rson].sum;
T[rt].end = T[lson].end & T[rson].end;
}

void build(int l, int r, int rt)
{
T[rt].l = l; T[rt].r = r; T[rt].m = (r + l) >> 1;
T[rt].sum = T[rt].end = 0;
if (l == r)
{
//        T[rt].sum = end = 0;
}
else
{
build(l, T[rt].m, lson);
build(T[rt].m + 1, r, rson);
}
}

void updateP(int p, int a, int rt)
{
if (T[rt].l == T[rt].r)
{
T[rt].sum += a;
T[rt].end = 0;
}
else
{
if (p <= T[rt].m)
updateP(p, a, lson);
else
updateP(p, a, rson);
pushup(rt);
}
}

void updateS(int L, int R, int rt)
{
if (T[rt].end)
return;
if (T[rt].l == T[rt].r)
{
trim(T[rt].sum);
T[rt].end = 1;
}
else
{
if (L <= T[rt].m)
updateS(L, R, lson);
if (R > T[rt].m)
updateS(L, R, rson);
pushup(rt);
}
}

LL query(int L, int R, int rt)
{
if (L <= T[rt].l && T[rt].r <= R)
return T[rt].sum;
LL ret = 0;
if (L <= T[rt].m)
ret += query(L, R, lson);
if (R > T[rt].m)
ret += query(L, R, rson);
return ret;
}

int main()
{
int n, m, op, l, r;
init();
while (~RII(n, m))
{
build(1, n, 1);
REP(i, m)
{
RIII(op, l, r);
if (op == 1)
updateP(l, r, 1);
else if (op == 2)
printf("%I64d\n", query(l, r, 1));
else
updateS(l, r, 1);
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  acm 线段树