线段树 杭电 1166(入门)
来源:互联网 发布:裁剪照片的软件 编辑:程序博客网 时间:2024/06/05 19:20
参考了一下资料. http://blog.sina.com.cn/s/blog_86fff3d101019kf1.html
首先来说说线段树吧。
从我的理解来看 线段树 其实就是 一颗二叉树 能比较快的对数据进行维护和修改,时间复杂度是 O(log n),可想而知有多快。就如下图:
在[0,n](k=1)的区间上,其 left 叶子结点 是 [0,(0 + n)/2] (k =2*k);
right 叶子结点 是 [(0 + n)/2 +1,n] (k = 2*k+1); 以此类推。。
下面是代码操作:
1 建树
建树的第一步是定义一个结构体:
struct tree
{
int left,right,sum; //左右结点
}a[max * 4]; //a[k]
然后就到真真的建树的过程了:
void build(int l,int r,int k) // l表示要求的left结点 ,r 是right结点 ,k 表示的是第几个结构图储存
{
a[k].left = l; //让a[k] 中的左右叶子结点 都有记录。
a[k].right = r;
if(l == r) //相等 即 表示 这已经是在一点上了
{
a[k].sum = num[l];
return;
}
else //不相等 就递归建立 子树
{
int mid = (l + r)/2;
build(l,mid,2*k); //建立 a[1,mid]树
build(mid+1,r,2*k +1); //建立 a[mid + 1,r]树
a[k].sum = a[2*k].sum + a[2*k+1].sum;
}
}
2 操作分为2种
第一种 更新操作:
void update(int k,int index,int change) //k 表示更新哪一个,index表示需要修改的点
{
a[k].sum += change; //更改某点的值 使区间相应更改
//如果该线段已经是一个点了,结束更改
//否则 将值传递下去
if(a[k].left == a[k].right &&a[k].left==index)
{
return;
}
else
{
int mid = (a[k].right + a[k].left)/2;
if(index <= mid) // index 在 mid 的left 所以更新left结点的值
update(2*k,index,change);
else //在 right 所以更新 right结点的值。
update(2*k + 1,index,change);
}
}
第二种 查找:
int find(int l,int r,int k) //l,r 为要求的 区间长度,k为 开始
{
int sum = 0;
// 如果 给定的区间包含了 a[k]上的区间 则直接 可以加上去
if(l <= a[k].left&& r >= a[k].right )
{
sum = a[k].sum;
}
// 否则 查找该区间涵盖了左右树中的哪些区间
else
{
int mid = (a[k].left + a[k].right)>> 1;
if(mid < r ) //与 right 区间的交集
{
sum =sum + find(l,r,2*k+1);
}
if(l <= mid) //与 left 区间的交集
{
sum =sum + find(l,r,2*k);
}
}
return sum;
}
大功告成 。。。。
至于剩下的就简单了,至于1166 不罗嗦 上代码.
#include<stdio.h>
#define max 50005
int num[50005];
struct tree
{
int left,right,sum;
}a[max * 4];
void build(int l,int r,int k)
{
a[k].left = l;
a[k].right = r;
if(l == r)
{
a[k].sum = num[l];
return;
}
else
{
int mid = (l + r)/2;
build(l,mid,2*k);
build(mid+1,r,2*k +1);
a[k].sum = a[2*k].sum + a[2*k+1].sum;
}
}
void update(int k,int index,int change)
{
a[k].sum += change;
if(a[k].left == a[k].right &&a[k].left==index)
{
return;
}
else
{
int mid = (a[k].right + a[k].left)/2;
if(index <= mid)
update(2*k,index,change);
else
update(2*k + 1,index,change);
}
}
int find(int l,int r,int k)
{
int sum = 0;
if(l <= a[k].left&& r >= a[k].right)
{
sum += a[k].sum;
}
else
{
int mid = (a[k].left + a[k].right)>> 1;
if(mid < r )
{
sum =sum + find(l,r,2*k+1);
}
if(l <= mid)
{
sum =sum + find(l,r,2*k);
}
}
return sum;
}
int main()
{
int t;
while(~scanf("%d",&t))
{
for(int h = 1;h <= t;h++)
{
int n;
scanf("%d",&n);
for(int i = 1;i <= n;i++)
scanf("%d",&num[i]);
build(1,n,1);
//for(int i = 1;i <= n;i++)
//printf("%d %d %d%d\n",i,a[i].left,a[i].right,a[i].sum);
char op[10];
printf("Case %d:\n",h);
while(~scanf("%s",op) && op[0]!= 'E')
{
//printf("%d %d",x,y);
int x,y;
scanf("%d%d",&x,&y);
if(op[0] == 'Q')
{
printf("%d\n",find(x,y,1));
}
else if(op[0] == 'A')
{
update(1,x,y);
}
else if(op[0] == 'S')
{
update(1,x,-y);
}
}
}
}
}
0 0
- 线段树 杭电 1166(入门)
- HDU 1166 敌兵布阵 线段树
- poj 3321 Apple Tree 线段树
- poj 2182 Lost Cows 线段树
- 【线段树】 POJ 2828 Buy Tickets
- 杭电 2084
- 线段树入门 杭电 1166
- 完整版 线段树
- 01背包问题 杭电 2602
- 杭电 ACM 1014
- 杭电 human number1058
- 线段树 count color
- floyd 算法(基础) 杭电 1874
- poj 2352 Stars 线段树
- poj 3667 hotel 线段树…
- poj 3264 Balanced Lineup(线段树)
- poj 3368 Frequent values(线段树)
- poj 2892 Tunnel Warfare(线段树…
- expressjs运行原理
- 软件评价了解
- ios 动态添加了按钮,绑定同一个点击事件,如何判断点击的是哪个?
- 求最长公共子串
- leetcode第9题-Palindrom Number
- 线段树 杭电 1166(入门)
- Objective-C语法快速参考
- iOS 代理的传值使用
- IOS 中的 CoreData的使用
- iOS 中tableview的使用
- 欢迎使用CSDN-markdown编辑器
- B - Ignatius and the Princess IV (DP+模拟)
- 异步通信and同步通信
- 2014134027 谢天