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;
}
开始的时候,我按双标记,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;
}
相关文章推荐
- E - Just a Hook HDU 1698 (线段树+类似延迟标记)
- 线段树(类似延迟标记) HDU - 4027
- 【解题报告】 HDU 1698 Just a Hook 线段树 (线段替换) 插线问线 + 延时标记
- hdu 3911 Black And White(线段树的延迟标记法)
- hdu 4893 Wow! Such Sequence! 线段树
- hdu 4893 Wow! Such Sequence!(线段树和树状数组实现)--2014 Multi-University Training Contest 3
- hdu 4893 线段树
- hdu 3275线段树加延迟标记
- HDU 4893 线段树
- HDU 3397 线段树 双懒惰标记
- 闲着无聊,写两个线段树发现类似点。
- 【HDU】4893 Wow! Such Sequence! 线段树
- hdu 3397 Sequence operation(线段树的延迟标记)
- HDU 3954 Level up (线段树特殊懒惰标记)
- hdu 1828 Picture(线段树 || 普通hash标记)
- 【HDU 4893 多校联合】 Wow! Such Sequence!【线段树】
- hdu 1754 也是裸的线段树
- hdu 4027 Can you answer these queries? 线段树 懒惰标记 单点更新妙用
- HDU 4107(线段树 特殊懒惰标记)g++ TLE,c++才过(呜呜呜呜)
- HDU 4893 Wow! Such Sequence! 水线段树