Balanced Lineup
Time Limit: 5000MS   Memory Limit: 65536K
Total Submissions: 40687   Accepted: 19137
Case Time Limit: 2000MS

Description

For the daily milking, Farmer John's N cows (1 ≤ N ≤ 50,000) always line up in the same order. One day Farmer John decides to organize a game of Ultimate Frisbee with some of the cows. To keep things simple, he will take a contiguous range
of cows from the milking lineup to play the game. However, for all the cows to have fun they should not differ too much in height.

Farmer John has made a list of Q (1 ≤ Q ≤ 200,000) potential groups of cows and their heights (1 ≤ height ≤ 1,000,000). For each group, he wants your help to determine the difference in height between the shortest and the tallest
cow in the group.

Input

Line 1: Two space-separated integers, N and Q

Lines 2..N+1: Line i+1 contains a single integer that is the height of cow i 

Lines N+2..N+Q+1: Two integers A and B (1 ≤ A ≤ B ≤ N), representing the range of cows from A to B inclusive.

Output

Lines 1..Q: Each line contains a single integer that is a response to a reply and indicates the difference in height between the tallest and shortest cow in the range.

Sample Input

6 3
1
7
3
4
2
5
1 5
4 6
2 2

Sample Output

6
3
0

POJ3264,给出一个数组的N个数,然后给出Q个询问,每一个询问是求一段序列中最大值与最小值的差。

每一个点很明显存的就是最大值和最小值,现在看从这道题入手线段树是有些不好的,因为觉得这道题并没有展现出线段树的思想,只是套用了线段树的模式,然后最大值和最小值也很好表示,每一个点的最大值,来自于左右子树的最大值,最小值来自于左右子树的最小值。

然后这个查询,之前一直没注意第一个剪枝部分。

if (pRoot->nMin >= nMin&&pRoot->nMax <= nMax)
return;

其实第一个剪枝部分使得性能大幅度提升,而且个人觉得这个才是些微展露了线段树强大的地方

这道题是线段树最简单的模板了。

代码:

#include <iostream>
#include <algorithm>
#include <cmath>
#include <vector>
#include <string>
#include <cstring>
#pragma warning(disable:4996)
using namespace std; #define MY_MIN 99999999
#define MY_MAX -99999999 struct no
{
int L, R;//区间起点和终点
int nMin, nMax;//本区间的最小值和最大值
no *pLeft, *pRight;
}; int nMax, nMin;
no Tree[1000000];
int ncount = 0; void BuildTree(no *pRoot, int L, int R)
{
pRoot->L = L;
pRoot->R = R; pRoot->nMin = MY_MIN;
pRoot->nMax = MY_MAX; if (L != R)
{
ncount++;
pRoot->pLeft = Tree + ncount; ncount++;
pRoot->pRight = Tree + ncount; BuildTree(pRoot->pLeft, L, (L + R) / 2);
BuildTree(pRoot->pRight, (L + R) / 2 + 1, R);
}
} void Insert(no *pRoot, int i, int v)
{
if (pRoot->L == i&&pRoot->R == i)
{
pRoot->nMin = pRoot->nMax = v;
return;
}
pRoot->nMin = min(v, pRoot->nMin);
pRoot->nMax = max(v, pRoot->nMax); if (i <= (pRoot->L + pRoot->R) / 2)
{
Insert(pRoot->pLeft, i, v);
}
else
{
Insert(pRoot->pRight, i, v);
}
} void Query(no * pRoot, int s, int e)
{
if (pRoot->nMin >= nMin&&pRoot->nMax <= nMax)
return; if (s == pRoot->L&&e == pRoot->R)
{
nMin = min(pRoot->nMin, nMin);
nMax = max(pRoot->nMax, nMax);
return;
} if (e <= (pRoot->L + pRoot->R) / 2)
{
Query(pRoot->pLeft,s,e);
}
else if (s >= (pRoot->L + pRoot->R) / 2 + 1)
{
Query(pRoot->pRight,s,e);
}
else
{
Query(pRoot->pLeft, s, (pRoot->L + pRoot->R) / 2);
Query(pRoot->pRight, (pRoot->L + pRoot->R) / 2+1, e);
}
} int n, q; int main()
{
int i, h, s, e; scanf("%d%d", &n, &q);
BuildTree(Tree, 1, n);
ncount = 0; for (i = 1; i <= n; i++)
{
scanf("%d", &h);
Insert(Tree, i, h);
}
for (i = 1; i <= q; i++)
{
scanf("%d%d", &s, &e); nMax = MY_MAX;
nMin = MY_MIN; Query(Tree, s, e);
printf("%d\n", nMax - nMin);
}
return 0;
}
A Simple Problem with Integers
Time Limit: 5000MS   Memory Limit: 131072K
Total Submissions: 79715   Accepted: 24583
Case Time Limit: 2000MS

Description

You have N integers, A1A2, ... , AN. You need to deal with two kinds of operations. One type of operation is to add some given number to each number in a given interval. The other is
to ask for the sum of numbers in a given interval.

Input

The first line contains two numbers N and Q. 1 ≤ N,Q ≤ 100000.

The second line contains N numbers, the initial values of A1A2, ... , AN. -1000000000 ≤ Ai ≤ 1000000000.

Each of the next Q lines represents an operation.

"C a b c" means adding c to each of AaAa+1, ... , Ab. -10000 ≤ c ≤ 10000.

"Q a b" means querying the sum of AaAa+1, ... , Ab.

Output

You need to answer all Q commands in order. One answer in a line.

Sample Input

10 5
1 2 3 4 5 6 7 8 9 10
Q 4 4
Q 1 10
Q 2 4
C 3 6 3
Q 2 4

Sample Output

4
55
9
15

Hint

The sums may exceed the range of 32-bit integers.

这道题也是给出了一个N个数的序列,比之前难在不只是查询,还有动态的对数组一段元素的相加,第一次做的时候没有用inc,直接就是sum,然后每次相加都是搞到叶子节点,这样的话实际就是浪费了线段树节省时间的功能,就是线段树是属于不见棺材不落泪的类型,我只要恰好覆盖了你要求的区间,我就坚决不往下走了,除非你要查询叶子节点,否则我根据我上面点记录的信息就可以回答你了何必走到叶子节点呢?

说白了,这题inc起到的就是不用继续往下面走的作用。

代码:

#include <iostream>
#include <algorithm>
#include <cmath>
#include <vector>
#include <string>
#include <cstring>
#pragma warning(disable:4996)
using namespace std; struct no
{
int L, R;
long long sum;
long long inc;
no * pLeft;
no * pRight;
}Tree[200002]; int n, q;
long long ncount; void BuildTree(no * pRoot, int L, int R)
{
pRoot->L = L;
pRoot->R = R; pRoot->sum = 0;
pRoot->inc = 0; if (L != R)
{
ncount++;
pRoot->pLeft = Tree + ncount; ncount++;
pRoot->pRight = Tree + ncount; BuildTree(pRoot->pLeft, L, (L + R) / 2);
BuildTree(pRoot->pRight, (L + R) / 2 + 1, R);
}
} void Insert(no *pRoot, int i, long long h)
{
if (pRoot->L == i&&pRoot->R == i)
{
pRoot->sum = h;
return;
}
pRoot->sum += h; if (i <= (pRoot->L + pRoot->R) / 2)
{
Insert(pRoot->pLeft, i, h);
}
else
{
Insert(pRoot->pRight, i, h);
}
} void Add(no *pRoot, int s, int e, long long val)
{
if (pRoot->L == s&&pRoot->R == e)
{
pRoot->inc += val;
return;
} pRoot->sum += val*(e - s + 1); if (e <= (pRoot->L + pRoot->R) / 2)
{
Add(pRoot->pLeft, s, e,val);
}
else if (s >= (pRoot->L + pRoot->R) / 2 + 1)
{
Add(pRoot->pRight, s, e,val);
}
else
{
Add(pRoot->pLeft, s, (pRoot->L + pRoot->R) / 2,val);
Add(pRoot->pRight, (pRoot->L + pRoot->R) / 2 + 1, e,val);
}
} long long Query(no *pRoot, int s, int e)
{
if (pRoot->L == s&&pRoot->R == e)
{
return pRoot->sum + (pRoot->R - pRoot->L + 1)*pRoot->inc;
}
pRoot->sum = pRoot->sum + (pRoot->R - pRoot->L + 1)*pRoot->inc; Add(pRoot->pLeft, pRoot->L, (pRoot->L + pRoot->R) / 2, pRoot->inc);
Add(pRoot->pRight, (pRoot->L + pRoot->R) / 2 + 1, pRoot->R, pRoot->inc);
pRoot->inc = 0; if (e <= (pRoot->L + pRoot->R) / 2)
{
return Query(pRoot->pLeft, s, e);
}
else if (s >= (pRoot->L + pRoot->R) / 2 + 1)
{
return Query(pRoot->pRight, s, e);
}
else
{
return Query(pRoot->pLeft, s, (pRoot->L + pRoot->R) / 2) + Query(pRoot->pRight, (pRoot->L + pRoot->R) / 2 + 1, e);
}
} int main()
{
int i, h, s, e;
long long val;
char oper; scanf("%d%d", &n, &q);
BuildTree(Tree, 1, n);
ncount = 0; for (i = 1; i <= n; i++)
{
scanf("%d", &h);
Insert(Tree, i, h);
}
for (i = 1; i <= q; i++)
{
cin >> oper;
if (oper == 'Q')
{
cin >> s >> e;
printf("%lld\n", Query(Tree, s, e));
}
else if (oper == 'C')
{
cin >> s >> e >> val;
Add(Tree, s, e, val);
}
}
return 0;
}
Time Limit: 1000MS   Memory Limit: 65536KB   64bit IO Format: %I64d & %I64u

Submit Status

Description

Chosen Problem Solving and Program design as an optional course, you are required to solve all kinds of problems. Here, we get a new problem. 



There is a very long board with length L centimeter, L is a positive integer, so we can evenly divide the board into L segments, and they are labeled by 1, 2, ... L from left to right, each is 1 centimeter long. Now we have to color the board - one segment
with only one color. We can do following two operations on the board: 



1. "C A B C" Color the board from segment A to segment B with color C. 

2. "P A B" Output the number of different colors painted between segment A and segment B (including). 



In our daily life, we have very few words to describe a color (red, green, blue, yellow…), so you may assume that the total number of different colors T is very small. To make it simple, we express the names of colors as color 1, color 2, ... color T. At the
beginning, the board was painted in color 1. Now the rest of problem is left to your. 

Input

First line of input contains L (1 <= L <= 100000), T (1 <= T <= 30) and O (1 <= O <= 100000). Here O denotes the number of operations. Following O lines, each contains "C A B C" or "P A B" (here A, B, C are integers, and A may be larger than B) as an operation
defined previously.

Output

Ouput results of the output operation in order, each line contains a number.

Sample Input

2 2 4
C 1 1 2
P 1 2
C 2 2 2
P 1 2

Sample Output

2
1

这题我终于感觉摸到了线段树的门。。。想了一个晚上之前金学长的代码里cover变量的作用。。。后来发现就是之前Add函数里面inc的作用,这两个本质是相同的。就是获得整块区间就将inc改为true,当要对其子节点操作的时候在现有节点的信息基础上对子节点进行修改。

线段树就是“当线段恰好覆盖一个节点的区间就直接对该节点操作而不再向下操作。绝对不能把区间内所有节点全部一代到底,到叶子节点。”金教授说的太好了。

代码:

#include <iostream>
#include <algorithm>
#include <cmath>
#include <vector>
#include <string>
#include <cstring>
#pragma warning(disable:4996)
using namespace std; struct no
{
int L,R;
int col;
bool inc;
}tree1[900000]; int L1,T,O; void buildtree(int root,int L,int R)
{
tree1[root].L=L;
tree1[root].R=R; tree1[root].col=1;
tree1[root].inc=false; if(L!=R)
{
buildtree((root<<1)+1,L,(L+R)/2);
buildtree((root<<1)+2,(L+R)/2+1,R);
}
} void insert(int root,int L,int R,int color)
{
if(tree1[root].L==L&&tree1[root].R==R)
{
tree1[root].inc=true;
tree1[root].col= (1<<(color-1));
return ;
}
if(tree1[root].inc)
{
tree1[root].inc=false; tree1[(root<<1)+1].col = tree1[root].col;
tree1[(root<<1)+2].col = tree1[root].col; tree1[(root<<1)+1].inc = true;
tree1[(root<<1)+2].inc = true;
}
int mid = (tree1[root].L + tree1[root].R)/2;
if(R<=mid)
{
insert((root<<1)+1,L,R,color);
}
else if(L>=mid+1)
{
insert((root<<1)+2,L,R,color);
}
else
{
insert((root<<1)+1,L,mid,color);
insert((root<<1)+2,mid+1,R,color);
}
tree1[root].col = tree1[(root<<1)+1].col | tree1[(root<<1)+2].col;
} int query(int root,int L,int R)
{
if(tree1[root].inc==true ||tree1[root].L==L && tree1[root].R==R)
{
return tree1[root].col;
}
int mid = (tree1[root].L + tree1[root].R)/2;
if(R<=mid)
{
return query((root<<1)+1,L,R);
}
else if(L>=mid+1)
{
return query((root<<1)+2,L,R);
}
else
{
return query((root<<1)+1,L,mid)|query((root<<1)+2,mid+1,R);
}
} void out(int x)
{
int cnt=0;
while(x!=0)
{
cnt += (x&1);
x=x>>1;
}
printf("%d\n",cnt);
} int main()
{
//freopen("i.txt","r",stdin);
//freopen("o.txt","w",stdout); int i,s,e,color_s;
string op;
scanf("%d%d%d",&L1,&T,&O); buildtree(0,1,L1);
for(i=1;i<=O;i++)
{
cin>>op;
if(op=="C")
{
scanf("%d%d%d",&s,&e,&color_s);
insert(0,s,e,color_s);
}
else
{
scanf("%d%d",&s,&e);
int res=query(0,s,e);
out(res);
}
} //system("pause");
return 0;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

几道简单的线段树入门题 POJ3264&&POJ3468&&POJ2777的更多相关文章

  1. hdu 1166敌兵布阵(线段树入门题)

    >>点击进入原题测试<< 思路:这两天在学线段树,这个题直接手敲一下线段树就行了,都没有用上懒人标记.入门题 cin,cout会超时,记得加std::ios::sync_wit ...

  2. [poj2104]可持久化线段树入门题(主席树)

    解题关键:离线求区间第k小,主席树的经典裸题: 对主席树的理解:主席树维护的是一段序列中某个数字出现的次数,所以需要预先离散化,最好使用vector的erase和unique函数,很方便:如果求整段序 ...

  3. hiho1079 - 数据结构 线段树(入门题,离散化)

    题目链接 描述 小Hi和小Ho在回国之后,重新过起了朝7晚5的学生生活,当然了,他们还是在一直学习着各种算法~ 这天小Hi和小Ho所在的学校举办社团文化节,各大社团都在宣传栏上贴起了海报,但是贴来贴去 ...

  4. Mosaic HDU 4819 二维线段树入门题

    Mosaic Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 102400/102400 K (Java/Others)Total S ...

  5. A Simple Problem with Integers(线段树入门题)

    Description You have N integers, A1, A2, ... , AN. You need to deal with two kinds of operations. On ...

  6. HDU1698(线段树入门题)

    Just a Hook Time Limit:2000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u Descrip ...

  7. POJ3264(线段树入门题)

    Balanced LineupCrawling in process... Crawling failed Time Limit:5000MS     Memory Limit:65536KB     ...

  8. hiho1080 - 数据结构 线段树(入门题,两个lazy tag)

    题目链接 维护区间和,两个操作:一个是将某个区间设置成一个值,一个是将某个区间增加一个固定值 /**************************************************** ...

  9. hdu 1754 I Hate It 线段树基础题

    Problem Description 很多学校流行一种比较的习惯.老师们很喜欢询问,从某某到某某当中,分数最高的是多少. 这让很多学生很反感. 不管你喜不喜欢,现在需要你做的是,就是按照老师的要求, ...

随机推荐

  1. 41和为S的连续正数序列+注意循环条件记一下这题特殊解法

    题目描述 小明很喜欢数学,有一天他在做数学作业时,要求计算出9~16的和,他马上就写出了正确答案是100.但是他并不满足于此,他在想究竟有多少种连续的正数序列的和为100(至少包括两个数).没多久,他 ...

  2. 106、Java中String类之使用contains()方法判断子字符串是否存在

    01.代码如下: package TIANPAN; /** * 此处为文档注释 * * @author 田攀 微信382477247 */ public class TestDemo { public ...

  3. Mac的VIM中delete键失效的原因和解决方案

    在Mac的键盘上实际是没有backspace这个键的.其实Mac的delete就是Windows的backspace,实现的都是向左删除的功能.Mac上如果要实现向右删除的功能需要使用⌘+delete ...

  4. 写的一个轻量级javascript框架的设计模式

    公司一直使用jQuery框架,一些小的项目还是觉得jQuery框架太过于强大了,于是自己周末有空琢磨着写个自己的框架.谈到js的设计模式,不得不说说js的类继承机制,javascript不同于PHP可 ...

  5. 多元线性回归算法python实现(非常经典)

    对于多元线性回归算法,它对于数据集具有较好的可解释性,我们可以对比不过特征参数的输出系数的大小来判断它对数据的影响权重,进而对其中隐含的参数进行扩展和收集,提高整体训练数据的准确性.整体实现代码如下所 ...

  6. ls查看所有文件

    ls -al   查看所有文件,包括隐藏文件

  7. JS开发常用工具函数

    1.isStatic:检测数据是不是除了symbol外的原始数据 function isStatic(value) { return ( typeof value === 'string' || ty ...

  8. kali 中文乱码解决方法

    本文转自https://www.cnblogs.com/sym945/p/11943842.html#4449966 1.更换阿里源 vim /etc/apt/sources.list,编辑源之后,a ...

  9. OpenJ_Bailian - 1088 滑雪(记忆化搜索)

    题意:给定一个二维数组,一个人可以从某个点滑向上下左右相邻四个点之一,当且仅当高度减小,输出可以滑行的最长区域的长度. 分析:对于每一个点,进行记忆化搜索.若某点可以向四周某几个点滑行,记忆化搜索求出 ...

  10. stm32串口收发导致的死机

    stm32串口收发导致的死机 很久以前有偶尔遇到过串口死机的情况,那是当时的我写出来的代码自己都觉得有问题,也就没注意.用了stm32做项目以后也就没遇到过了,今天做了个高压测试,每5ms定时发送一次 ...