码迷,mamicode.com
首页 > 其他好文 > 详细

hdu 4893 线段树 --- 也是两个变 类似双标记

时间:2014-08-08 21:29:26      阅读:276      评论:0      收藏:0      [点我收藏+]

标签:des   http   os   io   for   问题   代码   amp   

http://acm.hdu.edu.cn/showproblem.php?pid=4893


开始的时候,我按双标记,WA了一下午,搞不定,我是用的两个标记add--表示当前结点中有值发生变化,flag,斐波那契的懒惰标记,但是估计是我自己处理的有问题,一直不对

参考了别人的代码,写法还是很不错的,Add变量维护的是,完全变成Fibonacci的时候的和,---回头我再重新写一遍

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <string>
#include <iostream>
#include <cmath>
#include <map>
#include <queue>
using namespace std;

#define ls(rt) rt*2
#define rs(rt) rt*2+1
#define ll long long
#define rep(i,s,e) for(int i=s;i<e;i++)
#define repe(i,s,e) for(int i=s;i<=e;i++)
#define CL(a,b) memset(a,b,sizeof(a))
#define IN(s) freopen(s,"r",stdin)
#define OUT(s) freopen(s,"w",stdin)

const int MAXN =100000+100;
ll ff[105];
ll num[MAXN];

void init()
{
    ff[0]=ff[1]=1;
    for(int i=2;i<105;i++)
        ff[i]=ff[i-1]+ff[i-2];
}

ll cal(ll x)
{
    if(x == 0)return 1;
    int idx=lower_bound(ff,ff+105,x)-ff;
    //if(ff[idx] == x || idx==0)return ff[idx];//
    if(x-ff[idx-1]<=ff[idx]-x)return ff[idx-1];
    else return ff[idx];
}

struct Node{
    int l,r;
    ll sum;
    ll add;//区间内某个值被改过,如果进行FF操作,需要将当前结点dfs
    int flag;//1,区间内有值变过/初始的时候,如果有fi区间更新的话需要重新更新 0--已经更新过程斐波那契,不需要更新
}nodes[MAXN*4];

void build(int rt, int l, int r)
{
    nodes[rt].l=l;
    nodes[rt].r=r;
    nodes[rt].sum=0;
    nodes[rt].add=1;//没有做过fi修改
    nodes[rt].flag=0;
    if(l==r)
    {
        num[l]=0;
        return;
    }
    int mid=(l+r)/2;
    build(ls(rt),l,mid);
    build(rs(rt),mid+1,r);
    if(nodes[rt].l==nodes[rt].r)return;
    nodes[rt].sum=nodes[ls(rt)].sum+nodes[rs(rt)].sum;
    nodes[rt].add=nodes[ls(rt)].add+nodes[rs(rt)].add;
}

/*void dfs(int rt)
{
    if(0 == nodes[rt].flag)return;//已经修改过斐波那契
    if(0 == nodes[rt].add)return;//区间内值没有做过修改
    nodes[rt].flag=0;//改过
    nodes[rt].add=0;
    if(nodes[rt].l == nodes[rt].r)
    {
        nodes[rt].sum=num[nodes[rt].l]=cal(num[nodes[rt].l]);
        return;
    }
    dfs(ls(rt));
    dfs(rs(rt));
    nodes[rt].sum=nodes[ls(rt)].sum+nodes[rs(rt)].sum;
}*/
void pushdown(int rt)
{
    if(nodes[rt].flag && nodes[rt].l==nodes[rt].r)
    {
        nodes[rt].sum=nodes[rt].add;
        nodes[rt].flag=0;
        return;
    }
    if(nodes[rt].flag)
    {
        nodes[ls(rt)].flag=nodes[rs(rt)].flag=1;
        nodes[ls(rt)].sum=nodes[ls(rt)].add;
        nodes[rs(rt)].sum=nodes[rs(rt)].add;
        nodes[rt].flag=0;
    }
}
void modify(int rt, int p, ll v)
{
    if(nodes[rt].l==nodes[rt].r)
    {

        nodes[rt].sum+=v;
        nodes[rt].add=cal(nodes[rt].sum);
        num[nodes[rt].l]+=v;
        nodes[rt].flag=0;
        return;
    }
    pushdown(rt);
    //nodes[rt].add=1;//该节点的区间被修改过值,如果进行FF,需要dfs
    int mid=(nodes[rt].l+nodes[rt].r)/2;
    if(p<=mid)modify(ls(rt),p,v);
    else modify(rs(rt),p,v);
    if(nodes[rt].l==nodes[rt].r)return;
    nodes[rt].sum=nodes[ls(rt)].sum+nodes[rs(rt)].sum;
    nodes[rt].add=nodes[ls(rt)].add+nodes[rs(rt)].add;/////////
}

void update(int rt, int l, int r)
{
    if(nodes[rt].l==l && nodes[rt].r==r)
    {
        nodes[rt].flag=1;
            //需要修改
        nodes[rt].sum=nodes[rt].add;
        return;
    }
    pushdown(rt);
    int mid=(nodes[rt].l+nodes[rt].r)/2;
    if(r<=mid)update(ls(rt),l,r);
    else
    {
        if(l>mid)update(rs(rt),l,r);
        else
        {
            update(ls(rt),l,mid);
            update(rs(rt),mid+1,r);
        }
    }
    if(nodes[rt].l==nodes[rt].r)return;
    nodes[rt].sum=nodes[ls(rt)].sum+nodes[rs(rt)].sum;
    nodes[rt].add=nodes[ls(rt)].add+nodes[rs(rt)].add;
}

ll query(int rt, int l, int r)
{
    //if(nodes[rt].flag && nodes[rt].add)dfs(rt);
    if(nodes[rt].l == l && nodes[rt].r==r)
    {
        return nodes[rt].sum;
    }
    pushdown(rt);
    int mid=(nodes[rt].l+nodes[rt].r)/2;
    ll ret=0;
    if(r<=mid)ret= query(ls(rt),l,r);
    else
    {
        if(l>mid)ret= query(rs(rt),l,r);
        else
        {
            ret= query(ls(rt),l,mid)+query(rs(rt),mid+1,r);
        }
    }
    if(nodes[rt].l!=nodes[rt].r)
    {
         nodes[rt].sum=nodes[ls(rt)].sum+nodes[rs(rt)].sum;
         nodes[rt].add=nodes[ls(rt)].add+nodes[rs(rt)].add;
    }
    return ret;
}

int main()
{
    //IN("hdu4893.txt");
    int n,m,op,l,r;
    init();
    while(~scanf("%d%d",&n,&m))
    {
        build(1,1,n);
        while(m--)
        {
            scanf("%d",&op);
            scanf("%d%d",&l,&r);
            if(op == 1)
            {
                modify(1,l,r);
            }
            if(op == 3)
            {
                update(1,l,r);
            }
            if(op == 2)
            {
                printf("%I64d\n",query(1,l,r));
            }
        }
    }
    return 0;
}


hdu 4893 线段树 --- 也是两个变 类似双标记,布布扣,bubuko.com

hdu 4893 线段树 --- 也是两个变 类似双标记

标签:des   http   os   io   for   问题   代码   amp   

原文地址:http://blog.csdn.net/u011026968/article/details/38443539

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!