hdoj 4893 2014年多校联合3 1007
来源:互联网 发布:知乎美国大选 编辑:程序博客网 时间:2024/04/30 04:57
这道题可以说是标准的线段树的用法,单点更新+区间查询和修改。
不过这里有一个提前要做的工作,那就是每次单点更新的时候也要更新区间。否则的话,区间更新的时候,就得更新到叶子节点,复杂度就成了O(n)了。
那么怎么才能不更新到叶子节点呢,就是加一个标记,表示离它最近的斐波那契数列数。这样每次更新的时候,直接把斐波那契数赋值给sum就可以了。
单点更新的时候,才把标记一层一层的传递下去。
具体看代码吧。不过不知道为什么,C++ 一直WA,G++过了。表示很诧异。
#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#define maxn 111111using namespace std;struct Node{int l,r,c; //c是标记,表示这个区间或点要变成最近的斐波那契数__int64 sum,fsum; //sum是区间和,fsum是区间的斐波那契数的和};Node node[maxn*4];__int64 f[100];void init(){ int i; f[0]=f[1]=1; for(i=2;i<93;i++) f[i]=f[i-1]+f[i-2];}void pushup(int k) //向上更新{ node[k].sum=node[k*2].sum+node[k*2+1].sum;node[k].fsum=node[k*2].fsum+node[k*2+1].fsum;}void pushdown(int k) //向下传递{ if(node[k].l==node[k].r) return ; if(node[k].c) { node[k*2].c=node[k*2+1].c=1; node[k*2].sum=node[k*2].fsum; node[k*2+1].sum=node[k*2+1].fsum; node[k].c=0; }}void build_tree(int l,int r,int k) //建树{node[k].l=l;node[k].r=r;node[k].sum=0;node[k].c=0;node[k].fsum=1;if(l==r)return ;int m=(l+r)/2;build_tree(l,m,k*2);build_tree(m+1,r,k*2+1);pushup(k);}void Insert(int k,int num,int d) //单点更新,顺便更新最近的斐波那契数。这样才能为操作3省时。{ pushdown(k); if(node[k].l==node[k].r) { node[k].sum+=d; int i=lower_bound(f,f+93,node[k].sum)-f; if(i && abs(f[i]-node[k].sum)>=abs(f[i-1]-node[k].sum)) i=i-1; node[k].fsum=f[i]; return ; } int m=(node[k].l+node[k].r)/2; if(num<=m) Insert(k*2,num,d); else Insert(k*2+1,num,d); pushup(k);}void change(int k,int l,int r) //区间更新,打完标记就返回,不要更新到叶子节点。{ if(node[k].l>r||node[k].r<l) return ; if(l<=node[k].l&&node[k].r<=r) {node[k].c=1;node[k].sum=node[k].fsum;return ;} pushdown(k); change(k*2,l,r); change(k*2+1,l,r); pushup(k);}long long check(int k,int l,int r) //查询操作{ pushdown(k); if(node[k].l>r||node[k].r<l) return 0; if(l<=node[k].l&&node[k].r<=r) { return node[k].sum; } return check(k*2,l,r)+check(k*2+1,l,r);}int main(){ //freopen("1007.in","r",stdin); //freopen("1007.out","w",stdout);int i,j,k,op;int n,m,d,l,r;init();while(scanf("%d%d",&n,&m)!=EOF) { build_tree(1,n,1); for(i=0;i<m;i++) { scanf("%d",&op); if(op==1) { scanf("%d%d",&k,&d); Insert(1,k,d); } else if(op==3) { scanf("%d%d",&l,&r); change(1,l,r); } else { scanf("%d%d",&l,&r); printf("%I64d\n",check(1,l,r)); } } }return 0;}
0 0
- hdoj 4893 2014年多校联合3 1007
- HDU/HDOJ 3524 公式推导 2010年多校联合第九场
- hdoj 4939 2014多校联合7 1005
- HDU/HDOJ 3592 差分约束 World Exhibition 2010年多校联合第15场
- HDU/HDOJ 3440 差分约束 2010年多校联合第一场
- HDOJ 5752 (2016多校联合训练 Training Contest 3) Sqrt Bo
- HDOJ 5753 (2016多校联合训练 Training Contest 3) Permutation Bo
- HDOJ 5754 (2016多校联合训练 Training Contest 3) Life Winner Bo
- hdoj 4901 多校联合4 1005
- HDOJ多校联合第六场
- HDOJ多校联合第四场
- HDOJ多校联合第五场
- 2014年多校联合赛第二场1011
- HDOJ/HDU 3864 多校联合 D_num 数论
- HDU/HDOJ 3875 Euclidean Algorithm 多校联合第四场
- HDU/HDOJ R(N) 多校联合1
- HDU/HDOJ 3836 Equivalent Sets 多校联合1
- HDU/HDOJ 3908 Triple 多校联合7
- skype默认占用80和443端口
- 复习--C - Orders(字符串全排序,stl函数)
- OpenCV全屏显示图像H和W各有1像素的空白解决方法
- iOS6下UITextField垂直居中问题
- IE不能运行js,在IE浏览器js代码失效,js不能运行了怎么办
- hdoj 4893 2014年多校联合3 1007
- 2.自己总结的游戏框架小到中型游戏适用——从swf加载素材资源
- hdu4893 Wow! Such Sequence!,树状数组,线段树,单点修改,区间更新
- hdu 4888 Redraw Beautiful Drawings
- hdu4892 Defence of the Trees 最短路
- 数据结构--数组和广义表--以行逻辑链接的顺序表为存储结构的矩阵的基本运算(求矩阵乘积)
- an error has occurred.See the log file
- 工作问题积累(二十四)虚函数之进一步理解,结合汇编语言
- Single Number II