qduoj 21waterproblem 线段树的简单应用

来源:互联网 发布:pmp认证 知乎 编辑:程序博客网 时间:2024/05/22 10:52

water problem

发布时间: 2015年10月10日 15:34   时间限制: 1000ms   内存限制: 256M

题意很简单 

给你N个数, Q个查询

每次查询给你一个区间[L, R]

你要找出 [L, R] 这个区间里面取模M后的最大值。

第一行一个T,表示测试数据组数。 第二行两个整数N, M (1<=N<=10^5, 1<=M<=10^9)。 第三行给你N个整数 整数范围在1到10^9之间。 第四行给你一个整数Q. ( 1<=Q<=10^5) 下面Q行, 每一行对应两个整数L, R (1<=L<=R<10^9)

每一行对应一个询问的答案。

 复制
15 34 2 2 3 521 3 4 5
22
 此题类似于求给定一个区间的最大值问题,我们只需对数取模M 然后存到数组中即可;建立线段树时父结点保存左右节点中最大的,查找的第三种情况返回左右递归查找中最大的

ac代码:

#include<stdio.h>
#define MAXN  1000100
int t[MAXN],num[MAXN];
void build(int L,int R,int d)
{    if(L==R)
      {   t[d]=num[L];
           return ;
      }
      else
      {   int mid=(L+R)/2;
          build(L,mid,d*2);
          build(mid+1,R,2*d+1);
          
      }
      t[d]=t[2*d]>t[2*d+1]?t[2*d]:t[2*d+1];
}
int check(int L,int R,int l,int r,int d)
{         if(L==l&&R==r)
             return t[d];
           else
           {   int mid=(L+R)/2;
               if(r<=mid)
                  return check(L,mid,l,r,d*2);
               else if(l>mid)
                   return check(mid+1,R,l,r,2*d+1);
               else
                    return check(L,mid,l,mid,2*d)>check(mid+1,R,mid+1,r,2*d+1)? check(L,mid,l,mid,2*d):check(mid+1,R,mid+1,r,2*d+1);
           }
}
int main()
{   int T,i,N,M,l,r,X,q;
    scanf("%d",&T);
    while(T--)
    {    scanf("%d %d",&N,&M);
          for(i=1;i<=N;i++)
            {  scanf("%d",&X);
                num[i]=X%M;
            }
            build(1,N,1);
           scanf("%d",&q);
           for(i=0;i<q;i++)
           {   scanf("%d %d",&l,&r);
               int sum=check(1,N,l,r,1);
               printf("%d\n",sum);
           }
    }
    return 0;
}

                 欢迎大家指出我的错误,我一定会更加努力的!

 

1 0
原创粉丝点击