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

hdu 4893 线段树

2019年02月27日 ⁄ 综合 ⁄ 共 1805字 ⁄ 字号 评论关闭

思路:我的思路比较简单,也没有lazy操作。就是该干嘛干嘛,每次修改了向上更新下而已。对于每个节点我设一个b值,代表它下面的那些值是否都已经是斐波那契数了,这样在3操作时如果已经是了,就不必再往下更新了。仔细想,其实复杂度不大的。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
struct node
{
    int l,r;
    long long a;
    bool b;
}t[400000];
int n,m;
long long fei[100];
void build(int ll,int rr,int rot)
{
    t[rot].l=ll;t[rot].r=rr;
    t[rot].b=0;
    t[rot].a=0;
    if(ll==rr)return;
    int mid=(ll+rr)/2;
    build(ll,mid,rot<<1);
    build(mid+1,rr,rot<<1|1);
}
void add(int k,int d,int rot)
{
    if(k==t[rot].l&&k==t[rot].r)
    {
        t[rot].a+=d;
        t[rot].b=0;
        //cout<<"change "<<k<<"  "<<t[rot].a<<endl;
        return;
    }
    int mid=(t[rot].l+t[rot].r)/2;
    if(k<=mid)add(k,d,rot<<1);
    else add(k,d,rot<<1|1);
    t[rot].a=t[rot<<1].a+t[rot<<1|1].a;
    t[rot].b=0;
}
long long query(int ll,int rr,int rot)
{
    if(t[rot].l==ll&&t[rot].r==rr)return t[rot].a;
    int mid=(t[rot].l+t[rot].r)/2;
    if(rr<=mid)return query(ll,rr,rot<<1);
    else if(ll>mid)return query(ll,rr,rot<<1|1);
    else return query(ll,mid,rot<<1)+query(mid+1,rr,rot<<1|1);
}
long long go(long long x)
{
    if(x<=0)return 1ll;
    int w=lower_bound(fei+1,fei+90,x)-fei;
    if(fei[w]-x<x-fei[w-1])return fei[w];
    else return fei[w-1];
}
void update(int ll,int rr,int rot)
{
    //cout<<"up "<<t[rot].l<<" "<<t[rot].r<<endl;
    if(t[rot].l==ll&&t[rot].r==rr&&t[rot].b)return;
    if(t[rot].l==t[rot].r)
    {
        //cout<<"fei "<<ll<<"  from  "<<t[rot].a<<"  to  ";
        t[rot].a=go(t[rot].a);
        //cout<<t[rot].a<<endl;
        t[rot].b=1;
        return;
    }
    int mid=(t[rot].l+t[rot].r)/2;
    if(rr<=mid)update(ll,rr,rot<<1);
    else if(ll>mid)update(ll,rr,rot<<1|1);
    else
    {
        update(ll,mid,rot<<1);
        update(mid+1,rr,rot<<1|1);
    }
    t[rot].a=t[rot<<1].a+t[rot<<1|1].a;
    if(t[rot<<1].b&&t[rot<<1|1].b)t[rot].b=1;
    else t[rot].b=0;
}
int main()
{
    int l,r,u;
    fei[0]=1;fei[1]=1;
    for(int i=2;i<=90;i++)fei[i]=fei[i-2]+fei[i-1];
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        build(1,n,1);
        while(m--)
        {
            scanf("%d%d%d",&u,&l,&r);
            if(u==1)add(l,r,1);
            else if(u==2)printf("%I64d\n",query(l,r,1));
            else update(l,r,1);
        }
    }
    return 0;
}
【上篇】
【下篇】

抱歉!评论已关闭.