hdu 4893 线段树

来源:互联网 发布:直销软件制作xazxrj 编辑:程序博客网 时间:2024/06/07 07:08

思路:我的思路比较简单,也没有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;}


0 0