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

ST表

时间:2016-05-04 18:41:34      阅读:207      评论:0      收藏:0      [点我收藏+]

标签:

/*
ST表多次查询区间最小值
设 g[j][i] 表示从第 i 个数到第 i + 2 ^ j - 1 个数之间的最小值
类似DP的说 ans[i][j]=min (ans[i][mid],ans[mid+1][r])mid=(l+r)/2
but 数太大装不下 所以改一个g数组出来就好了
接下来考虑 g[i][j]由谁转移来(不漏下就好 因为是去min 可以重复 同理gcd也可以 其他的就要考虑考虑了)
解决方案是搞一个p[i] 表示长度为i的区间长度是2的p[i]次方(下取整) 
那么, ans[l][r]就可以不漏的表示
/*
ST表多次查询区间最小值
设 g[j][i] 表示从第 i 个数到第 i + 2 ^ j - 1 个数之间的最小值
类似DP的说 ans[i][j]=min (ans[i][mid],ans[mid+1][r])mid=(l+r)/2
but 数太大装不下 所以改一个g数组出来就好了
接下来考虑 g[i][j]由谁转移来(不漏下就好 因为是去min 可以重复 同理gcd也可以 其他的就要考虑考虑了)
解决方案是搞一个p[i] 表示长度为i的区间长度是2的p[i]次方(下取整) 
那么, ans[l][r]就可以不漏的表示为 min(g[w][l],g[w][r-(1<<w)+1])  (w=p[l-r+1])
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#define maxn 200010
using namespace std;
int n,m,a[maxn],g[21][maxn],p[maxn],f[21][maxn];
int init()
{
    int x=0;
    int f=0;
    char s;
    s=getchar();
    while(s<0||s>9)
      {
          if(s==-)f=1;
          s=getchar();
      }
    while(s>=0&&s<=9)
      {
          x=x*10+s-0;
          s=getchar();
      }
    if(f==0)return x;
    else return -x;
}
void slove()
{
    int i,j;
    for(i=1;i<=n;i++)
      {
          g[0][i]=a[i];
          f[0][i]=a[i];
      }
    for(i=1;i<=18;i++)
      for(j=0;j+(1<<i>>1)<=n;j++)
        g[i][j]=min(g[i-1][j],g[i-1][j+(1<<i>>1)]);
    for(i=1;i<=18;i++)
      for(j=0;j+(1<<i>>1)<=n;j++)
        f[i][j]=max(f[i-1][j],f[i-1][j+(1<<i>>1)]);
    memset(p,-1,sizeof(p));
    for(i=0;i<18;i++)
      p[1<<i]=i;
    for(i=0;i<maxn;i++)
      if(p[i]==-1)
        p[i]=p[i-1];
}
int find1(int l,int r)
{
    int w=p[r-l+1];
    return max(f[w][l],f[w][r-(1<<w)+1]);
}
int find2(int l,int r)
{
    int w=p[r-l+1];
    return min(g[w][l],g[w][r-(1<<w)+1]);
}
int main()
{
    n=init();m=init();
    int i,l,r;
    for(i=1;i<=n;i++)
      a[i]=init();
    slove();
    for(i=1;i<=m;i++)
      {
          l=init();r=init();
          if(l>r)swap(l,r);
          cout<<find1(l,r)-find2(l,r)<<endl;
      }
    return 0;
}

 

为 min(g[w][l],g[w][r-(1<<w)+1])  (w=p[l-r+1])
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#define maxn 10000001
using namespace std;
int n,m,a[maxn],g[21][maxn],p[maxn];
void slove()
{
    int i,j;
    for(i=1;i<=n;i++)
      g[0][i]=a[i];
    for(i=1;i<20;i++)
      for(j=1;j<=n;j++)
        g[i][j]=min(g[i-1][j],g[i-1][j+(1<<j>>1)]);
    for(i=0;i<20;i++)
      p[1<<i]=i;
    for(i=1;i<=n;i++)
      if(p[i]==0)p[i]=p[i-1];
}
int find(int l,int r)
{
    int w=p[l-r+1];
    return min(g[w][l],g[w][r-(1<<w)+1]);
}
int main()
{
    cin>>n;
    int i,l,r;
    for(i=1;i<=n;i++)
      cin>>a[i];
    slove();
    cin>>m;
    for(i=1;i<=m;i++)
      {
          cin>>l>>r;
          cout<<find(l,r)<<endl;
      }
    return 0;
}

 

ST表

标签:

原文地址:http://www.cnblogs.com/yanlifneg/p/5459217.html

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