码迷,mamicode.com
首页 > 其他好文 > 详细

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

时间:2015-05-31 01:17:36      阅读:268      评论:0      收藏:0      [点我收藏+]

标签:

题意:求在数列中能找到几个个长度为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:\n",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\n",number);
139         }
140     }
141     return 0;
142 }
View Code

 

   

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

标签:

原文地址:http://www.cnblogs.com/ACMERY/p/4541301.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!