• 2015百度之星1002 查找有序序列(RMQ+主席树模板水过)


    题意:求在数列中能找到几个个长度为k 的区间,里面的 k 个数字排完序后是连续的。

    思路:枚举范围,判断区间内是否有重复的数字(主席树),没有的话求区间最大-区间最小(RMQ),判断是否等于K,是的话sum++,否则continue;

     主席树:原理不太懂,暂时还没能到能研究的水平,不过知道时间复杂度之类的,以后希望能用到的时候不是敲完上交了才知道超时了。。。。

                  时间复杂度

       建树      O(n);

       更新     O(log(n));

       查询     O(log(n));

      1 #include <iostream>
      2 #include <cstdio>
      3 #include <cmath>
      4 #include <algorithm>
      5 #include <map>
      6 using namespace std;
      7 #define MAXN 50010
      8 #define Max(x,y) (x>y?x:y)
      9 #define Min(x,y) (x>y?y:x)
     10 int maxsum[MAXN][20],minsum[MAXN][20];//表示从第i个数起连续2^j个数中的最大值/最小值
     11 int num;
     12 void RMQ()
     13 {
     14     for(int j=1; j<20; j++)
     15         for(int i=1; i<=num; i++)
     16         {
     17             if(i+(1<<j)-1 <= num)
     18             {
     19                 maxsum[i][j]=Max(maxsum[i][j-1],maxsum[i+(1<<(j-1))][j-1]);
     20                 minsum[i][j]=Min(minsum[i][j-1],minsum[i+(1<<(j-1))][j-1]);
     21             }
     22         }
     23 }
     24 /*
     25 区间内是否有重复数字第几大的数字
     26 */
     27 const int M = MAXN * 100;
     28 int a[MAXN];
     29 int T[MAXN],lson[M],rson[M],c[M];
     30 int tot;
     31 int build(int l,int r)
     32 {
     33     int root = tot++;
     34     c[root] = 0;
     35     if(l != r)
     36     {
     37         int mid = (l+r)>>1;
     38         lson[root] = build(l,mid);
     39         rson[root] = build(mid+1,r);
     40     }
     41     return root;
     42 }
     43 int update(int root,int pos,int val)
     44 {
     45     int newroot = tot++, tmp = newroot;
     46     c[newroot] = c[root] + val;
     47     int l = 1, r = num;
     48     while(l < r)
     49     {
     50         int mid = (l+r)>>1;
     51         if(pos <= mid)
     52         {
     53             lson[newroot] = tot++;
     54             rson[newroot] = rson[root];
     55             newroot = lson[newroot];
     56             root = lson[root];
     57             r = mid;
     58         }
     59         else
     60         {
     61             rson[newroot] = tot++;
     62             lson[newroot] = lson[root];
     63             newroot = rson[newroot];
     64             root = rson[root];
     65             l = mid+1;
     66         }
     67         c[newroot] = c[root] + val;
     68     }
     69     return tmp;
     70 }
     71 int query(int root,int pos)
     72 {
     73     int ret = 0;
     74     int l = 1, r = num;
     75     while(pos < r)
     76     {
     77         int mid = (l+r)>>1;
     78         if(pos <= mid)
     79         {
     80             r = mid;
     81             root = lson[root];
     82         }
     83         else
     84         {
     85             ret += c[lson[root]];
     86             root = rson[root];
     87             l = mid+1;
     88         }
     89     }
     90     return ret + c[root];
     91 }
     92 int main()
     93 {
     94     int i,j,t,Query,kase = 1;
     95     while(scanf("%d%d",&num,&Query) != EOF)
     96     {
     97         for(i=1; i<=num; i++)
     98         {
     99             scanf("%d",&maxsum[i][0]);
    100             a[i] = maxsum[i][0];
    101             minsum[i][0]=maxsum[i][0];
    102         }
    103         RMQ();
    104         T[num+1] = build(1,num);
    105         map<int,int>mp;
    106         for(int i = num; i>= 1; i--)
    107         {
    108             if(mp.find(a[i]) == mp.end())
    109             {
    110                 T[i] = update(T[i+1],i,1);
    111             }
    112             else
    113             {
    114                 int tmp = update(T[i+1],mp[a[i]],-1);
    115                 T[i] = update(tmp,i,1);
    116             }
    117             mp[a[i]] = i;
    118         }
    119         int w,maxl,minl;
    120         printf("Case #%d:
    ",kase++);
    121         while(Query--)
    122         {
    123             scanf("%d",&w);
    124             int number = 0;
    125             for(int i = 1; i<=num; i++)
    126             {
    127                 int st = i,en = w+i-1;
    128                 int NUM = query(T[st],en);
    129                 if(NUM == w)
    130                 {
    131                     int k=(int)((log(en-st+1))/log(2.0));
    132                     maxl=Max(maxsum[st][k],maxsum[en-(1<<k)+1][k]);
    133                     minl=Min(minsum[st][k],minsum[en-(1<<k)+1][k]);
    134                     if(maxl - minl == w-1)
    135                         number++;
    136                 }
    137             }
    138             printf("%d
    ",number);
    139         }
    140     }
    141     return 0;
    142 }
    View Code

       

  • 相关阅读:
    MS SQL执行大脚本文件时,提示“未能完成操作,存储空间不足,无法处理此命令”的解决办法
    一、Flux 是什么?
    for...in for..of
    循环总结
    javascript中几种this指向问题
    redux
    布局方式
    js获取前几个月的具体日期
    动态引入js文件
    获取页面url信息
  • 原文地址:https://www.cnblogs.com/ACMERY/p/4541301.html
Copyright © 2020-2023  润新知