首页 > 代码库 > HDU 4893 Wow! Such Sequence 线段树暴力

HDU 4893 Wow! Such Sequence 线段树暴力


题意:n个数 初始为0,三个操作:给某个数加上d,查询区间和,把区间[l,r]中每个a[i]变为离a[i]最近的斐波那契数,n,m<=1e5.

无操作1情况下,每个点最多变化一次,每次修改logn,算上操作1 最坏情况下修改n+m次 O((n+m)logn). 
对区间设个标记 线段树暴力即可.

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod=1e9+7;
const int N=2e6+5;
struct node{
    int l,r;
    int mid(){return l+r>>1;} 
    ll flag,sum;
}t[N>>2];
int n,m;
ll f[200];
ll calc(ll x)
{
    ll mn=1e18,res;
    for(int i=1;i<=90;i++)
    {
        if(mn>abs(f[i]-x))
            mn=abs(f[i]-x),res=f[i];
    }
    return res;
}
void push_up(int rt)
{
    t[rt].sum=t[rt<<1].sum+t[rt<<1|1].sum;
    t[rt].flag=t[rt<<1].flag & t[rt<<1|1].flag;
}
void build(int rt,int l,int r)
{
    t[rt].l=l,t[rt].r=r;
    if(l==r)
    {
        t[rt].sum=0;
        t[rt].flag=0;
        return;
    }
    int m=t[rt].mid();
    build(rt<<1,l,m);
    build(rt<<1|1,m+1,r);
    push_up(rt);
}
void setval(int rt,int pos,int d)
{
    int l=t[rt].l,r=t[rt].r;
    if(l==r)
    {
        t[rt].sum+=d;
        t[rt].flag=0;
        return;
    }
    int m=t[rt].mid();
    if(pos<=m)
        setval(rt<<1,pos,d);
    else
        setval(rt<<1|1,pos,d);
    push_up(rt);
}
ll query(int rt,int ql,int qr)
{
    int l=t[rt].l,r=t[rt].r;
    if(ql<=l&&qr>=r)
        return t[rt].sum;
    ll m=t[rt].mid(),res=0;
    if(ql<=m)
        res+=query(rt<<1,ql,qr);
    if(qr>m)
        res+=query(rt<<1|1,ql,qr);
    return res;
}
void update(int rt,int ql,int qr)
{
    int l=t[rt].l,r=t[rt].r;
    if(ql<=l&&qr>=r && (t[rt].flag))
        return;
    if(l==r)
    {
        t[rt].sum=calc(t[rt].sum);
        t[rt].flag=1;
        return;
    }
    int m=t[rt].mid();
    if(ql<=m)
        update(rt<<1,ql,qr);
    if(qr>m)
        update(rt<<1|1,ql,qr);
    push_up(rt);
}
int main()
{
    f[0]=f[1]=1;
    for(int i=1;i<=90;i++)
        f[i]=f[i-1]+f[i-2];
    while(cin>>n>>m)
    {
        build(1,1,n);
        int op,k,d,l,r;
        while(m--)
        {
            scanf("%d",&op);
            if(op==1)
            {
                scanf("%d%d",&k,&d);
                setval(1,k,d);
            }
            else
            {
                scanf("%d%d",&l,&r);
                if(op==2)
                    printf("%I64d\n",query(1,l,r));
                else
                    update(1,l,r);
            }
        }
    }
    return 0;
}

不能直接一整个区间更新,因为有大量不必要的更新操作,算出每个点最多更新多少次,暴力单点

HDU 4893 Wow! Such Sequence 线段树暴力