现在的位置: 首页 > 综合 > 正文

hdu4893 Wow! Such Sequence!,树状数组,线段树,单点修改,区间更新

2018年12月23日 ⁄ 综合 ⁄ 共 3616字 ⁄ 字号 评论关闭

2014 Multi-University Training Contest 3  

1007题

点击打开链接

单点修改,区间更新(线段树Lazy标记)

树状数组:

/*
优化:
1、用set容器记录num[i]还不是Nearest Fibonacci number的下标i,
操作三时只需要更新set中在区间内的数,num[i] -> Nearest Fibonacci number,同时把i
从set中移除。
直到遇到操作一时才可能再把它加进来。 所以这样就大大减少了操作三的耗时。
2、二分找 Nearest Fibonacci number。
3、输入加速。

只要有优化一就可以通过这一题。。。。
*/

#include<cstring>
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<set>
#include<vector>

using namespace std;
typedef long long LL;

const int maxn = 100000 + 10;
int n, m;
LL C[maxn], num[maxn], f[maxn];
vector<int> vec;
set<int> s;

void Init()
{
    int  i;
    f[0]=1;
    f[1]=1;
    for(i=2; i<=91; i++) {
        f[i]=f[i-1]+f[i-2];
    }
}

int lowbit(int x)
{
    return x&(-x);
}
void update(int i, LL v)
{
    for(; i<=n; i += lowbit(i)) C[i] +=v;
}

LL getsum(int i)
{
    LL ret=0;
    for(; i>0; i-=lowbit(i)) ret +=C[i];
    return ret;
}

//适用于正整数
template <class T>
inline void scan_d(T &ret)
{
    char c;
    ret=0;
    while((c=getchar())<'0'||c>'9');
    while(c>='0'&&c<='9') ret=ret*10+(c-'0'),c=getchar();
}

LL Find(LL x)
{
    int t = lower_bound(f,f+92, x) - f;
    LL k;
    if(t==0) k = 1;
    else {
        if(abs(f[t]- x)<abs(x-f[t-1])) k =f[t];
        else k = f[t-1];
    }
    return k;
}

int main()
{
    Init();
    int  i, j;
    int  a, b, c;
    //freopen("in.txt","r",stdin);
    while(~scanf("%d%d", &n, &m)) {
        memset(num, 0, sizeof(LL)*(n+2) );
        memset(C, 0, sizeof(LL)*(n+2) );
        s.clear();
        set<int>::iterator pos;
        for(i=1; i<=n; ++i) s.insert(i);
        while(m--) {
            scan_d(a);
            scan_d(b);
            scan_d(c);
            //scanf("%d%d%d", &a, &b, &c);
            if(a==1) {
                update(b, c);
                num[b] += c;
                s.insert(b);
            } else if(a==2) {
                LL ans = getsum(c) - getsum(b-1);
                printf("%I64d\n", ans);
            } else if(a==3) {
                vec.clear();
                for( pos = s.lower_bound(b); ((*pos)<=c)&&(pos!=s.end());pos++) {
                    int p = *pos;
                    LL New = Find(num[p]);  //num[p] -> Nearest Fibonacci number
                    update(p, New - num[p]);
                    num[p] = New;
                    vec.push_back(p);
                }

                for(i=0; i<vec.size(); ++i)
                    s.erase(vec[i]);
            }
        }
    }
    return 0;
}

线段树:

#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>

using namespace std;
typedef long long LL;
const int maxn = 100000 + 10;
struct node {
    int l, r;
    LL sum, fibsum;
    int lazy;
} tree[maxn*4];

LL f[100];
void calc_fib()
{
    int i;
    f[0] = f[1] = 1;
    for(i=2; i<=91; ++i) f[i] = f[i-1] + f[i-2];
}

LL Find(LL x)
{
    int t = lower_bound(f, f+92, x) - f;
    LL k;
    if(t==0) k = 1;
    else {
        if(abs(f[t]- x)<abs(x-f[t-1])) k = f[t];
        else k = f[t-1];
    }
    return k;
}

void PushUp(int rt)
{
    tree[rt].sum = tree[rt<<1].sum + tree[rt<<1|1].sum;
    tree[rt].fibsum = tree[rt<<1].fibsum + tree[rt<<1|1].fibsum;
}

void PushDown(int rt)
{
    if(tree[rt].lazy) {
        tree[rt<<1].sum = tree[rt<<1].fibsum;
        tree[rt<<1|1].sum = tree[rt<<1|1].fibsum;
        tree[rt<<1].lazy = tree[rt<<1|1].lazy = 1;
        tree[rt].lazy = 0;
    }
}
void build(int rt, int l, int r)
{
    tree[rt].l = l;
    tree[rt].r = r;
    tree[rt].sum = tree[rt].fibsum = 0;
    tree[rt].lazy = 0;
    if(l == r) {
        tree[rt].sum = 0;
        tree[rt].fibsum = 1;
        return ;
    }
    int mid = (l+r)>>1;
    build(rt<<1, l, mid);
    build(rt<<1|1, mid+1, r);
    PushUp(rt);
}

void add(int rt, int pos, LL v)
{
    if(tree[rt].l == tree[rt].r) {
        tree[rt].lazy = 0;
        tree[rt].sum += v;
        tree[rt].fibsum = Find(tree[rt].sum );
        return ;
    }
    PushDown(rt);
    int mid = (tree[rt].l + tree[rt].r)>>1;
    if(pos<= mid)   add(rt<<1, pos, v);
    else            add(rt<<1|1, pos, v);
    PushUp(rt);
}

LL sum(int rt, int l, int r)
{
    if(l <= tree[rt].l && tree[rt].r <= r) {
        return tree[rt].sum;
    }
    PushDown(rt);
    int mid = (tree[rt].l + tree[rt].r)>>1;
    LL ret = 0;
    if(l<=mid) ret += sum(rt<<1, l, r);
    if(r > mid) ret += sum(rt<<1|1, l, r);
    return ret;
}

void update(int rt, int l, int r)
{
    if(l <= tree[rt].l && tree[rt].r <= r) {
        tree[rt].lazy = 1;
        tree[rt].sum = tree[rt].fibsum;
        return ;
    }
    PushDown(rt);
    int mid = (tree[rt].l + tree[rt].r)>>1;
    if(l<=mid) update(rt<<1, l, r);
    if(r >mid) update(rt<<1|1, l, r);
    PushUp(rt);
}

//适用于正整数
template <class T>
inline void scan_d(T &ret)
{
    char c;
    ret=0;
    while((c=getchar())<'0'||c>'9');
    while(c>='0'&&c<='9') ret=ret*10+(c-'0'),c=getchar();
}

int main()
{
    int n, m;
    int op, l, r;
   // freopen("in.txt","r",stdin);
    calc_fib();
    while(~scanf("%d%d", &n, &m)) {
        build(1,1,n);
        while(m--) {
            scan_d(op);
            scan_d(l);
            scan_d(r);
            //scanf("%d%d%d", &op, &l, &r);
            if(op==1) add(1, l, r);
            if(op==2) printf("%I64d\n", sum(1, l, r));
            if(op==3) update(1, l, r);
        }
    }
    return 0;
}

抱歉!评论已关闭.