zoukankan      html  css  js  c++  java
  • POJ_3368 Frequent values 【线段树+区间查询】

    一、题面

    POJ3368

    二、分析

    仍然是一道只需要区间查询不需要区间修改的线段树题。

    这题的题面比较特别,它是一组非减的数组。当需要去找一段区间内出现次数最多的数字时,这些数字必然是连续的,那么就可以用线段树维护区间内出现的最大次数时,同时维护两端的数字出现的次数。这样,就可以在建树的时候通过判断可能的左右子树最大值和(左子树的最右端的数的次数+右子树的最左端的数的次数),括号出现的前提是左子树维护的区间右端点的数与右子树维护的区间左端点的数相等。

    保证建树建成功后,就是基本的查询了,但是需要注意的是,当mid在要查询的区间内时,因为查询的区间跨了线段树的两个区间,所以当左子树维护的右端点的值和右子树的左端点的值相等时,需要与当前最大值进行比较。

    二刷这题后,补充一下,初始化的问题,每组样例过后,记得对线段树的一些标记是改变了的。

    三、AC代码

      1 #include <cstdio>
      2 #include <iostream>
      3 #include <cstring>
      4 #include <algorithm>
      5 
      6 using namespace std;
      7 
      8 const int MAXN = 1e5;
      9 
     10 struct Node
     11 {
     12     int l, r;
     13     int cntl, cntr, Max;
     14 }segTree[MAXN<<2];
     15 int Data[MAXN], Ans;
     16 
     17 void Build(int v, int L, int R)
     18 {
     19     segTree[v].l = L;
     20     segTree[v].r = R;
     21     if(L == R)
     22     {
     23         segTree[v].Max = 1;
     24         segTree[v].cntl = segTree[v].cntr = 1;
     25         return;
     26     }
     27     int mid = (L + R) >> 1;
     28     int lc = v<<1, rc = v<<1|1;
     29     Build(lc, L, mid);
     30     Build(rc, mid + 1, R);
     31     int sum = 0;        //初始化别忘了
     32     if(Data[segTree[lc].r] == Data[segTree[rc].l])
     33     {
     34         sum = segTree[lc].cntr + segTree[rc].cntl;
     35     }
     36     if(segTree[lc].Max > segTree[rc].Max)
     37         segTree[v].Max = segTree[lc].Max;
     38     else
     39         segTree[v].Max = segTree[rc].Max;
     40     segTree[v].Max = max(segTree[v].Max, sum);
     41     segTree[v].cntl = segTree[lc].cntl;
     42     segTree[v].cntr = segTree[rc].cntr;
     43     if(Data[segTree[v].l] == Data[segTree[rc].l])
     44     {
     45         segTree[v].cntl += segTree[rc].cntl;
     46     }
     47     if(Data[segTree[v].r] == Data[segTree[lc].r])
     48     {
     49         segTree[v].cntr += segTree[lc].cntr;
     50     }
     51 }
     52 
     53 void Query(int v, int L, int R)
     54 {
     55     if(Ans >= segTree[v].Max)
     56         return;
     57     if(segTree[v].l == L && segTree[v].r == R)
     58     {
     59         Ans = max(Ans, segTree[v].Max);
     60         return;
     61     }
     62     int mid = (segTree[v].l + segTree[v].r)>>1;
     63     if(L > mid)
     64     {
     65         Query(v<<1 | 1, L, R);
     66     }
     67     else if(R <= mid)
     68     {
     69         Query(v<<1, L, R);
     70     }
     71     else
     72     {
     73         Query(v<<1, L, mid);
     74         Query(v<<1 | 1, mid + 1, R);
     75         int temp = 0;
     76         if(Data[mid] == Data[mid + 1])
     77         {
     78             temp = min(segTree[v<<1].cntr, mid - L + 1);
     79             //为什么要考虑mid-L+1,因为可能所插叙的区间并没有完全包含所有的这个数
     80             temp += min(segTree[v<<1|1].cntl, R - mid);
     81         }
     82         Ans = max(Ans, temp);
     83     }
     84 }
     85 
     86 int main()
     87 {
     88     //freopen("input.txt", "r", stdin);
     89     int N, Q;
     90     while(scanf("%d", &N) == 1 && N)
     91     {
     92         scanf("%d", &Q);
     93         int L, R;
     94         for(int i = 1; i <= N; i++)
     95             scanf("%d", &Data[i]);
     96         Build(1, 1, N);
     97         for(int i = 0; i < Q; i++)
     98         {
     99             Ans = -MAXN;
    100             scanf("%d %d", &L, &R);
    101             Query(1, L, R);
    102             printf("%d
    ", Ans);
    103         }
    104     }
    105 }
  • 相关阅读:
    synchronized (lock) 买票demo 线程安全
    springboot项目搭建
    Maven命令
    Mybatis的mapper文件中$和#的用法及区别详解
    mybatis映射文件mapper.xml的写法(collections...)
    MyBatis-动态SQL的if、choose、when、otherwise、trim、where、set、foreach使用(各种标签详解), 以及实体间关系配置
    024 搭建前台系统-----乐优商城工程启动步骤教程
    023 商品管理功能03-----商品修改
    023 商品管理功能02-----商品新增
    022 商品管理功能01-----商品查询
  • 原文地址:https://www.cnblogs.com/dybala21/p/10581154.html
Copyright © 2011-2022 走看看