您的位置:首页 > 其它

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

2014-08-08 19:24 295 查看
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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: