线段树区间更新--hdu3577
来源:互联网 发布:汉王pdf识别软件 编辑:程序博客网 时间:2024/06/03 18:54
改版的线段树题
本来是花了将近一个钟理解了一次线段树区间更新的版再加上自己把之前线段树版改了下,然后就打算随便找一道区间更新的题套个版看看自己的版对不对,结果套了这道改版的题,样例过了之后妥妥的交了一发,结果wa了,然后又改了点无关紧要的bug,结果又wa了。。然后就套了几个数据把版打出来看。。结果发现我用区间求和的方式把子节点的所有值都加了起来,但是他不需要所有子节点的和啊!!!然后马上又改了下版,一交,又wa了。。。郁闷了很久,感觉我敲的版没错啊。。然后默默的看向了push_up。。好吧这里写错了。。这里还是写成了区间求和。。所以说不是所有版都能乱用的。即使是自己敲出来的。也要更加深刻的去理解里面的意义。不然套版都不会。。。
hdu可用网址
hdu暂时不能用网址
下面先给出hdu3577 ac代码,再给出线段树区间更新的版
/****************create by QuanQcreate time 2016-9-2example hdu3577algorithm 线段树区间更新 *****************/#include <stdio.h>#include <string.h>#include <iostream>#include <algorithm>using namespace std;#define maxn 1000005#define ll long longstruct SegTree{ //线段树 int l,r,v; //lr左右孩子,v值 int add; //用来记录还没有更新的值 }tree[maxn << 2];/*更新当前父节点的值*/void push_up(int root){ tree[root].v = max(tree[root << 1].v,tree[root << 1 | 1].v); //寻找儿子节点最大值}/*将父节点中还没有加上的值给儿子节点加上*/void push_down(int root){ tree[root << 1].add += tree[root].add; tree[root << 1 | 1].add += tree[root].add; tree[root << 1].v += tree[root].add;//此处更新当前儿子节点的值 tree[root << 1 | 1].v += tree[root].add; tree[root].add = 0; }/*创建线段树*/void build_sTree(int root,int left,int right){ tree[root].l = left; tree[root].r = right; tree[root].add = 0; tree[root].v = 0; //总和,初始化为0 if(left < right){ int mid = (left + right) >> 1; build_sTree(root << 1,left,mid); //创建左孩子 build_sTree(root << 1 | 1,mid + 1,right); //创建右孩子 }}/*加入值/更新值*/void insert_sTree(int value,int root,int left,int right){ //有些代码也叫update,更新值 /*传入参数:value增加的值,root当前根部--通常传入时为1,need需要更改的key,add新增加的值*/ if(right < tree[root].l || left > tree[root].r) return; if(left <= tree[root].l && right >= tree[root].r){ tree[root].v += value; tree[root].add += value; return; } if(tree[root].add) push_down(root); int mid = (tree[root].l + tree[root].r) >> 1; if(right <= mid) insert_sTree(value,root << 1,left,right); else if(left > mid) insert_sTree(value,root << 1 | 1,left,right); else{ insert_sTree(value,root << 1,left,mid); insert_sTree(value,root << 1 | 1,mid + 1,right); } //最后出栈的时候更新数据 push_up(root);}/*查找--区间求和*/int search_sTree(int root,int l,int r){ /*传入参数:root当前根部--通常传入时为1,l,r,为所需要从l开始到r的所有数据的区间段,l一定要小于r*/ int mid = (tree[root].l + tree[root].r) >> 1; if(l == tree[root].l && r == tree[root].r) //如果找到了相应的位置,直接返回值 return tree[root].v; if(tree[root].add) push_down(root); if(r <= mid) //如果当前搜索的节点范围比正常范围大,则向左移动 return search_sTree(root << 1,l,r); else if(l > mid) //如果当前搜索的节点范围比正常范围小,则向右移动 return search_sTree(root << 1 | 1,l,r); else //寻找儿子节点当前人数最大值 return max(search_sTree(root << 1,l,mid),search_sTree(root << 1 | 1,mid + 1,r));}int ans[maxn];int main(){ int T,n,value,a,b,k,q; scanf("%d",&T); for(ll t = 1;t <= T;t++){ q = 0; build_sTree(1,1,maxn); scanf("%d %d",&k,&n); printf("Case %d:\n",t); for(int i = 1;i <= n;i++){ scanf("%d %d",&a,&b); if(search_sTree(1,a,b - 1) < k){ insert_sTree(1,1,a,b - 1); ans[q++] = i; } } for(int i = 0;i < q;i++) printf("%d ",ans[i]); printf("\n\n"); }}/*13 61 61 63 41 51 22 4*/
线段树区间更新版
struct SegTree{ //线段树 int l,r,v; //lr左右孩子,v值 int add; //用来记录还没有更新的值 }tree[maxn << 2];/*更新当前父节点的值*/void push_up(int root){ tree[root].v = tree[root << 1].v + tree[root << 1 | 1].v;}/*将父节点中还没有加上的值给儿子节点加上*/void push_down(int root){ tree[root << 1].add += tree[root].add; tree[root << 1 | 1].add += tree[root].add; tree[root << 1].v += tree[root].add * (tree[root << 1].r - tree[root << 1].l + 1); //此处更新当前儿子节点的值 tree[root << 1 | 1].v += tree[root].add * (tree[root << 1 | 1].r - tree[root << 1 | 1].l + 1); tree[root].add = 0; }/*创建线段树*/void build_sTree(int root,int left,int right){ tree[root].l = left; tree[root].r = right; tree[root].add = 0; tree[root].v = 0; //总和,初始化为0 if(left < right){ int mid = (left + right) >> 1; build_sTree(root << 1,left,mid); //创建左孩子 build_sTree(root << 1 | 1,mid + 1,right); //创建右孩子 }}/*加入值/更新值*/void insert_sTree(int value,int root,int left,int right){ //有些代码也叫update,更新值 /*传入参数:value增加的值,root当前根部--通常传入时为1,need需要更改的key,add新增加的值*/ if(right < tree[root].l || left > tree[root].r) return; if(left <= tree[root].l && right >= tree[root].r){ tree[root].v += value * (tree[root].r - tree[root].l + 1); tree[root].add += value; return; } if(tree[root].add) push_down(root); int mid = (tree[root].l + tree[root].r) >> 1; if(right <= mid) insert_sTree(value,root << 1,left,right); else if(left > mid) insert_sTree(value,root << 1 | 1,left,right); else{ insert_sTree(value,root << 1,left,mid); insert_sTree(value,root << 1 | 1,mid + 1,right); } //最后出栈的时候更新数据 push_up(root);}/*查找--区间求和*/int search_sTree(int root,int l,int r){ /*传入参数:root当前根部--通常传入时为1,l,r,为所需要从l开始到r的所有数据的区间段,l一定要小于r*/ int mid = (tree[root].l + tree[root].r) >> 1; if(l == tree[root].l && r == tree[root].r) //如果找到了相应的位置,直接返回值 return tree[root].v; if(tree[root].add) push_down(root); if(r <= mid) //如果当前搜索的节点范围比正常范围大,则向左移动 return search_sTree(root << 1,l,r); else if(l > mid) //如果当前搜索的节点范围比正常范围小,则向右移动 return search_sTree(root << 1 | 1,l,r); else //如果被当前区间分割,则分开两部分计算 return search_sTree(root << 1,l,mid) + search_sTree(root << 1 | 1,mid + 1,r);}
0 0
- 线段树区间更新--hdu3577
- HDU3577:Fast Arrangement(线段树区间更新+lazy)
- 【线段树区间修改】hdu3577
- hdu3577-Fast Arrangement 线段树区间覆盖
- HDU3577 离散化+线段树
- 线段树区间更新
- 线段树区间更新
- 线段树 区间更新
- 线段树区间更新
- 线段树-区间更新
- 线段树区间更新
- 线段树区间更新
- 线段树区间更新
- 区间更新线段树
- 线段树区间更新
- 线段树 区间更新
- 线段树区间更新
- poj2991 线段树区间更新
- EXTJS-GridPanel双击行 事件
- 设计移动App的十大技巧
- 黑马程序员:Python时代已到来!此时不学更待何时?
- C++中的类与对象
- 微软的那些区块链云服务
- 线段树区间更新--hdu3577
- js 基础之三种申明方式
- 安装QTP破解版工具不成功的解决办法
- JS对象克隆及JS继承
- OBS源码学习笔记(二)
- root 权限
- 如何更改linux文件的拥有者及用户组(chown和chgrp)
- android百分比布局
- 智能指针详解