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

来源:互联网 发布:软件项目开发文档 编辑:程序博客网 时间:2024/05/15 14:11

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;}


1 0