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
- hdu 4893 线段树 --- 也是两个变 类似双标记
- 线段树(类似延迟标记) HDU
- HDU 4902 双标记线段树
- hdu 3397 线段树双标记
- hdu 3397 线段树双标记
- E - Just a Hook HDU 1698 (线段树+类似延迟标记)
- hdu 3954 线段树 (标记)
- hdu 4902 线段树双标记类型题
- 线段树单标记,双标记
- hdu 1698 线段树 懒惰标记
- HDU 4339 (线段树字符标记)
- hdu 4578 线段树lazy标记
- hdu 4578 线段树(标记处理)
- 郁闷的出纳员 (splay的区间标记模板,删除区间,add标记,类似线段树)
- 闲着无聊,写两个线段树发现类似点。
- hdu 3397 Sequence operation (线段树+区间合并+双Lazy标记)
- hdu 1556 Color the ball(线段树+懒惰标记)
- hdu 3397 线段树+区间合并+懒惰标记 好题
- 金庸说:创造一个功夫永远比学功夫的人厉害
- 【Oracle练习】②第3章 限制数据和对数据排序
- HDU2680Choose the best route
- 女生程序员的路:向左,向右
- 恢复 Ubuntu 的面板到默认设置
- hdu 4893 线段树 --- 也是两个变 类似双标记
- Android短信管理
- 经典DP问题
- 离线版MSDN下载地址
- hdu-2187悼念512汶川大地震遇难同胞——老人是真饿了(贪心)
- Java中无法引用没有包、默认包、顶级类
- poj2299--B - Ultra-QuickSort(线段树,离散化)
- 设计模式概述【整理】
- 在centos6中同时使用python2和python3