poj 3368 线段树

这道题是要查询某个区间内数字出现的最大次数,序列不降,可以用线段树来做。

每个结点维护左右端点的值和出现次数(长度)以及该区间的Frequent values,然后向上合并即可。

 1 #include <iostream>
 2 #include <cstring>
 3 #include <cstdio>
 4 using namespace std;
 5
 6 const int N = 100001;
 7 int a[N];
 8
 9 struct Node
10 {
11     int l, r;
12     int lval, rval;
13     int len, llen, rlen;
14     friend Node operator + ( const Node & ln, const Node & rn )
15     {
16         Node res;
17         res.l = ln.l;
18         res.r = rn.r;
19         res.lval = ln.lval;
20         res.rval = rn.rval;
21         res.llen = ln.llen;
22         if ( ln.lval == ln.rval && ln.rval == rn.lval )
23         {
24             res.llen += rn.llen;
25         }
26         res.rlen = rn.rlen;
27         if ( ln.rval == rn.lval && rn.lval == rn.rval )
28         {
29             res.rlen += ln.rlen;
30         }
31         res.len = max( ln.len, rn.len );
32         if ( ln.rval == rn.lval )
33         {
34             res.len = max( res.len, ln.rlen + rn.llen );
35         }
36         return res;
37     }
38 } node[N << 2];
39
40 void build( int i, int l, int r )
41 {
42     if ( l == r )
43     {
44         node[i].l = node[i].r = l;
45         node[i].lval = node[i].rval = a[l];
46         node[i].len = node[i].llen = node[i].rlen = 1;
47         return ;
48     }
49     int mid = ( l + r ) >> 1;
50     build( i << 1, l, mid );
51     build( i << 1 | 1, mid + 1, r );
52     node[i] = node[i << 1] + node[i << 1 | 1];
53 }
54
55 Node query( int i, int l, int r )
56 {
57     if ( node[i].l == l && node[i].r == r )
58     {
59         return node[i];
60     }
61     int mid = ( node[i].l + node[i].r ) >> 1;
62     if ( r <= mid )
63     {
64         return query( i << 1, l, r );
65     }
66     else if ( l > mid )
67     {
68         return query( i << 1 | 1, l, r );
69     }
70     else
71     {
72         return query( i << 1, l, mid ) + query( i << 1 | 1, mid + 1, r );
73     }
74 }
75
76 int main ()
77 {
78     int n, m;
79     while ( scanf("%d", &n), n )
80     {
81         scanf("%d", &m);
82         for ( int i = 1; i <= n; i++ )
83         {
84             scanf("%d", a + i);
85         }
86         build( 1, 1, n );
87         while ( m-- )
88         {
89             int a, b;
90             scanf("%d%d", &a, &b);
91             Node ans = query( 1, a, b );
92             printf("%d\n", ans.len);
93         }
94     }
95     return 0;
96 }
时间: 2024-08-30 11:08:46

poj 3368 线段树的相关文章

POJ 3368 线段树,给定区间求连续不降序列的在该区间内出现最多的数

Frequent values Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 13771   Accepted: 5045 Description You are given a sequence of n integers a1 , a2 , ... , an in non-decreasing order. In addition to that, you are given several queries cons

POJ 2528 (线段树+离散化) Mayor&#39;s posters

因为将每个单位都作为一个最小单元的话会爆内存的 所以,将海报的每个端点进行排序,将这些端点最为最小的区间. 毕竟是刚刚接触线段树,理解起来还有些吃力,还是那句话,题做多了慢慢就好了. 萌萌的AC代码君贴上. 1 //#define LOCAL 2 #include <iostream> 3 #include <algorithm> 4 #include <cmath> 5 using namespace std; 6 7 int n; 8 struct CPost 9

poj 2777 线段树的区间更新

Count Color Time Limit: 1000 MS Memory Limit: 65536 KB 64-bit integer IO format: %I64d , %I64u Java class name: Main [Submit] [Status] [Discuss] Description Chosen Problem Solving and Program design as an optional course, you are required to solve al

转载::POJ 2991 线段树+计算几何(有c++结构体操作)

POJ 2991 线段树+计算几何 (2011-02-27 21:13:44) 转载▼ 标签: 杂谈 分类: OI 话说这一题真的是很恶心很恶心,不过确实改变了我对线段树的一些看法,算是很经典的题目. 题意:有一个吊车由很多个不同长度的线段组成,一开始是一条长直线起点在(0,0),尾节点在(0,sum[n]),每条线段之间的夹角的初始值是180度.然后有一些操作a. b将第a条线段和a+1之间的夹角变成b度,经过每一次操作都要求出尾节点的坐标. 首先要用到一个计算几何的知识(没学过..请教而来)

poj 2750(线段树的动态规划)

Potted Flower Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 4186   Accepted: 1581 Description The little cat takes over the management of a new park. There is a large circular statue in the center of the park, surrounded by N pots of f

POJ 2570 线段树

Potted Flower Time Limit: 2000 MS Memory Limit: 65536 KB 64-bit integer IO format: %I64d , %I64u Java class name: Main [Submit] [Status] [Discuss] Description The little cat takes over the management of a new park. There is a large circular statue in

poj 2828 线段树

http://poj.org/problem?id=2828 学到的思维: 1.变化的或者后来的优先影响前面的,那么从最后一个往前看,最后一个就成了 确定的, 并且后来的也可以确定----如果从前往后,所有的随时都不是确定的 2.线段树叶子节点直接维护区间(线段)信息,非叶子节点v维护的是以v为树根的整个子树的信息,那么假设父节点rt信息为[l,r]那么左子树维护[l,mid],右子树维护[mid+1,r]的信息.如果如果是前缀和,rt里是1-n的和,左子树1~n/2的和,右子树是n/2+1~n

POJ 3468 线段树+lazy标记

lazy标记 Time Limit:5000MS     Memory Limit:131072KB     64bit IO Format:%I64d & %I64u Submit Status Description You have N integers, A1, A2, ... , AN. You need to deal with two kinds of operations. One type of operation is to add some given number to

POJ 3667 线段树的区间合并简单问题

题目大意:有一排标号1-N的房间.操作一:询问是不是有连续长度为a的空房间,有的话住进最左边(占用a个房间)操作二:将[a,a+b-1]的房间清空(腾出b个房间)思路:记录每个区间中“靠左”“靠右”“中间”的空房间线段树操作:update:区间替换query:询问满足条件的最左端点 题目链接: http://vjudge.net/problem/viewProblem.action?id=10354 题目操作: 因为这里找从最左边住起的房间,所以这里不能像常规地写query函数那样写了,终于发现