HDU-1166-敌兵布阵(线段树)
前言:
线段树是一种二叉搜索树,与区间树相似,它将一个区间划分成一些单元区间,每个单元区间对应线段树中的一个叶结点。 对于线段树中的每一个非叶子节点[a,b],它的左儿子表示的区间为[a,(a+b)/2],右儿子表示的区间为[(a+b)/2+1,b]。因此线段树是平衡二叉树,最后的子节点数目为N,即整个线段区间的长度。 使用线段树可以快速的查找某一个节点在若干条线段中出现的次数,时间复杂度为O(logN)。而未优化的空间复杂度为2N,因此有时需要离散化让空间压缩。
题目链接
http://acm.hdu.edu.cn/showproblem.php?pid=1166
这个题直接用暴力的话,超时。
可以用,线段树,快很多,
这是我做的第一个线段树的题。
线段树可以分为几个部分
第一 建树
第二 插入数据
第三 查找数据
我的AC代码
#include<stdio.h> #include<string.h>
#define MAXSIZE 50005
struct node
{
int left,right,sum;
} tree[MAXSIZE*4];
void build(int node,int left,int right)//建树,二分的思路
{
tree[node].left=left;
tree[node].right=right;
tree[node].sum=0;
if(left==right) //如果左边界与右边界相等,则说明不能再二分了即就是,像一棵二叉树一样到了最低了;
return ;
int mid=(left+right)/2;
build(node*2,left,mid);
build(node*2+1,mid+1,right);
}
void update(int node,int pos,int val)//插入数据,更新数据
{
tree[node].sum+=val;
if(tree[node].left==pos&&tree[node].right==pos)
return ;
int mid=(tree[node].left+tree[node].right)/2;
if(pos<=mid)
update(node*2,pos,val);
else
update(node*2+1,pos,val); }
int query(int node,int left,int right) //查找数据,
{
if(tree[node].left==left&&tree[node].right==right)
return tree[node].sum;
int mid=(tree[node].left+tree[node].right)/2;
if(right<=mid)
return query(node*2,left,right);
else if(left>mid)
return query(node*2+1,left,right);
else
return query(node*2,left,mid)+query(node*2+1,mid+1,right);
}
int main(void)
{
int t,n,k,i;
int x,y,c;
char s[20];
scanf("%d",&t);
k=0;
while(t--)
{
scanf("%d",&n);
build(1,1,n);
printf("Case %d:\n",++k);
for(i=1; i<=n; i++)
{
scanf("%d",&c);
update(1,i,c);
}
while(scanf("%s",s)==1&&s[0]!='E')
{
scanf("%d%d",&x,&y);
if(s[0]=='Q')
{
printf("%d\n",query(1,x,y));
}
else if(s[0]=='A')
{
update(1,x,y);
}
else if(s[0]=='S')
{
update(1,x,-y);
}
}
}
return 0;
}
网上代码
#include <stdio.h> #include <string.h> #define MAXSIZE 50001
struct node { int left, right ; int sum ; }tree[MAXSIZE * 4];
int tcase, n ;
void build (int node, int left, int right) { tree[node].left = left ; tree[node].right = right ; tree[node].sum = 0 ; if (left == right) return ; int mid = (left + right) / 2 ; build (node * 2, left, mid) ; build (node * 2 + 1, mid + 1, right) ; }
void update (int node, int pos, int val) { // 当前区间的总人数增加 tree[node].sum += val ; // 刚好走到第pos 个营地所在的叶子 if (tree[node].left == pos &&tree[node].right == pos) { return ; } int mid = (tree[node].left + tree[node].right) / 2 ; // 若营地在当前区间的左半边 if (pos <= mid) update (node * 2, pos, val) ; // 若营地在当前区间的右半边 else update (node * 2 + 1, pos, val) ; }
int query (int node, int left, int right) { // 若区间刚好匹配 if (tree[node].left == left &&tree[node].right == right) return tree[node].sum ;
// 若区间无交集 //if (tree[node].left > right ||tree[node].right < left) //return 0 ;
// 若区间有交集 int mid = (tree[node].left + tree[node].right) / 2 ;
// 若查询区间在左半边 if (right <= mid) return query (node * 2, left, right) ; // 若查查询区间在右半边 else if (mid < left) return query (node * 2 + 1, left, right) ; // 若查询区间横跨当前区间的中点 else return query (node * 2, left, mid) + query (node * 2 + 1, mid + 1, right) ; }
int main () { char str[20] ; int i, j ; int x, y ;
while (scanf ("%d", &tcase) != EOF) { for (j = 1 ; j <= tcase ; ++j) { scanf ("%d", &n) ; build (1, 1, n) ; for (i = 1 ; i <= n ; ++i) { scanf ("%d", &x) ; // 从根部开始查找,第i 个营地的值增加x update (1, i, x) ; } printf ("Case %d:\n", j) ; while (scanf ("%s", str), *str != 'E') { scanf ("%d%d", &x, &y) ; if (*str == 'Q') printf ("%d\n", query (1, x, y)) ; else if (*str == 'A') update (1, x, y) ; else if (*str == 'S') update (1, x, -y) ; } } } return 0 ; }
HDU-1166-敌兵布阵(线段树)的更多相关文章
- HDU.1166 敌兵布阵 (线段树 单点更新 区间查询)
HDU.1166 敌兵布阵 (线段树 单点更新 区间查询) 题意分析 加深理解,重写一遍 代码总览 #include <bits/stdc++.h> #define nmax 100000 ...
- hdu 1166 敌兵布阵 线段树 点更新
// hdu 1166 敌兵布阵 线段树 点更新 // // 这道题裸的线段树的点更新,直接写就能够了 // // 一直以来想要进线段树的坑,结果一直没有跳进去,今天算是跳进去吧, // 尽管十分简单 ...
- HDU 1166 敌兵布阵(线段树单点更新,板子题)
敌兵布阵 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Submi ...
- HDU 1166 敌兵布阵(线段树单点更新)
敌兵布阵 单点更新和区间更新还是有一些区别的,应该注意! [题目链接]敌兵布阵 [题目类型]线段树单点更新 &题意: 第一行一个整数T,表示有T组数据. 每组数据第一行一个正整数N(N< ...
- HDU 1754 线段树 单点跟新 HDU 1166 敌兵布阵 线段树 区间求和
I Hate It Time Limit: 9000/3000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total ...
- HDU 1166 敌兵布阵 <线段树 单点修改 区间查询>
敌兵布阵 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submis ...
- hdu 1166 敌兵布阵 (线段树、单点更新)
敌兵布阵Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submiss ...
- hdu 1166 敌兵布阵 线段树区间修改、查询、单点修改 板子题
题目链接:敌兵布阵 题目: C国的死对头A国这段时间正在进行军事演习,所以C国间谍头子Derek和他手下Tidy又开始忙乎了.A国在海岸线沿直线布置了N个工兵营地,Derek和Tidy的任务就是要监视 ...
- HDU 1166 敌兵布阵 线段树
敌兵布阵 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submis ...
- HDU 1166 - 敌兵布阵 - [线段树][树状数组]
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1166 Time Limit: 2000/1000 MS (Java/Others) Memory Li ...
随机推荐
- ExtJS的4.1新特性简要介绍
ExtJS的4.1新特性简要介绍 一.动态加载机制 Ext.require动态加载任何类,并且会加载依赖类: 二.新类系统 •类定义:ExtJS4.0以后应入了Ext.define方法,他通过类的字符 ...
- ecos的mvcl
m 数据模型抽象层 v 视图 c 控制器 l 业务逻辑 mvc与mvcl区别 mvc中的m是mvcl中m+l
- JS基础知识(五)
内置对象 定义:JS语言自己定义的一些对象,供开发者使用. 常用内置对象: 1.Arguments对象 arguments.length 返回实参的个数 他只在正运行的函数内部使用.argument ...
- Polipo
polipo代理服务器简介 HTTP代理polipo的配置与使用:http://wuwei5460.blog.51cto.com/2893867/1407369/
- 在MAC下配置MySQL 5.7 数据库的编码问题
1.MySQL 5.7 for MAC 默认没有my.cnf文件 ,首先 新建my.cnf文件: 2.在my.cnf文件追加 [mysqld] character-set-server=utf8mb4 ...
- 笔记:利用 Cocos2dx 3.2 与 Box2D制作一个跑酷游戏(上)
最近写lua写得没有力气了,所以想让脑袋放松一下,刚好看到有人在用swift做游戏: Swift游戏实战-跑酷熊猫 于是脑子一短路,就想到了利用这些素材来做一个游戏. 本来不想记笔记的,但是由于选择物 ...
- 前端教程&开发模块化/规范化/工程化/优化&工具/调试&值得关注的博客/Git&面试-资源汇总
内容精简 资源这么多,多看看多学习再总结肯定是好的.多读读就算看重了不算浪费时间,毕竟一千个读者就有一千个林黛玉,还有温故而知新,说不定多读一些内容,就发现惊喜了呢.不过,在此也精简一些内容,就1~2 ...
- ASP.NET Security
<authentication mode="Forms"> <forms loginUrl="~/Account/Login" timeout ...
- greenDAO简介
了解android开发的人应该都会知道,android的数据库开发主要用到sqlite.greenDAO应该算是当前最火的数据库开源框架了吧,它是一个移动开发的ORM(object / relatio ...
- 为什么无线信号(RSSI)是负值(转)
源:为什么无线信号(RSSI)是负值 为什么无线信号(RSSI)是负值 答:其实归根到底为什么接收的无线信号是负值,这样子是不是容易理解多了.因为无线信号多为mW级别,所以对它进行了极化,转化为dBm ...