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

FZU1862(线段树 或者 DP)

时间:2015-08-11 23:04:01      阅读:130      评论:0      收藏:0      [点我收藏+]

标签:

技术分享 Problem 1862 QueryProblem

Accept: 100    Submit: 249
Time Limit: 2000 mSec    Memory Limit : 32768 KB

技术分享 Problem Description


There are N numbers (non-negative integers) in a circle. Now your task is quite simple, just tell me the largest number between L and R.
The Figure 1 is a sample of five integers in a circle. (marked with their index, but not their exact value.)
技术分享
Figure 1.

The Figure 2,3 show how we count the number.
技术分享

Figure 2.

技术分享

Figure 3.

技术分享 Input

There are no more than 10 test cases;

For each case, the first line contains only one integer N, indicates the size of the circle.

The following one line contains N non-negative integers where Mi indicates the i-th integers whose index is i. (1 <= N <= 1000, 1 <= i <= N, 0 <= Mi <= 10^9)

Then one line contains Q indicates the number of querys. (1 <= Q <= 10^5)

Then the next Q lines, each line contains only two integers indicate L and R (1 <= L,R <= N)

技术分享 Output

For each case, please output “Case #index:” in a single line, here index is the case index starts from one.

For each query just output a single line indicates the largest number between L and R.

Output a blank line after each case.

技术分享 Sample Input

2 3 8 3 1 1 1 2 2 1 1 9 1 1 1

技术分享 Sample Output

Case #1: 3 8 8 Case #2: 9

技术分享 Hint

Huge Input, please “scanf” to avoid time limit exceed.

题意:在给定的区间中查询最大的数。当L>R时,R =R +n 来改变R这也是2*n的原因;

方法1:线段树

收获:函数中的num指的是线段树上的编号,而当le == ri时,le 或 ri指的是最低层的编号。

#include <cstdio>
#include <iostream>
#include <cstdlib>
#include <algorithm>
#include <ctime>
#include <cmath>
#include <string>
#include <cstring>
#include <stack>
#include <queue>
#include <list>
#include <vector>
#include <map>
#include <set>
using namespace std;

const int INF=0x3f3f3f3f;
const double eps=1e-10;
const double PI=acos(-1.0);
#define maxn 8006
int tre[maxn];
int a[maxn/4];
int n;
void build(int num, int le, int ri)
{
    if(le == ri)
    {
        if(le > n)
            tre[num] = a[le-n];//函数中的num指的是线段树上的编号,而当le == ri时,le 或 ri指的是最低层的编号。
        else
            tre[num] = a[le];
        return;
    }
    int mid = (le + ri)/2;
    build(num*2, le, mid);
    build(num*2+1, mid+1, ri);
    tre[num] = max(tre[num*2], tre[num*2+1]);
}
int query(int num,int le,int ri,int x,int y)
{
    if(x<=le&&y>=ri)
        return tre[num];
    int mid=(le+ri)/2;
    int ans=0;
    if(x<=mid)
        ans=max(ans,query(num*2,le,mid,x,y)); //先查询左边
    if(y>mid)
        ans=max(ans,query(num*2+1,mid+1,ri,x,y)); //再查询右边
    return ans;
}
int main()
{
    int cas = 1;
    while(~scanf("%d", &n))
    {
        for(int i = 1; i <= n; i++)
            scanf("%d", &a[i]);
        build(1, 1, 2*n);
        int m;
        scanf("%d", &m);
        int a, b;
        printf("Case #%d:\n", cas++);
        for(int j = 0; j < m; j++)
        {
            scanf("%d%d", &a, &b);
            if(b < a)
                b = b + n;
            printf("%d\n", query(1, 1, 2*n, a, b));
        }
        puts("");
    }
}

方法2:DP

收获:对dp有了更多的了解。

dp[i][j]指的是i到j这个区间内保存的最大值。

#include <cstdio>
#include <iostream>
#include <cstdlib>
#include <algorithm>
#include <ctime>
#include <cmath>
#include <string>
#include <cstring>
#include <stack>
#include <queue>
#include <list>
#include <vector>
#include <map>
#include <set>
#define C 0.57721566490153286060651209
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1


using namespace std;

typedef long long LL;
const int INF=0x3f3f3f3f;
const double eps=1e-10;
const double PI=acos(-1.0);

const int maxn=1000009;
int dp[2020][2020];
int a[2020];
int main()
{
    int n, b;
    int sum=0;
    while(~scanf("%d", &n))
    {
        for(int i = 1; i <= n; i++)
        {
            scanf("%d", &b);
            a[i]=a[i+n]=b;
        }
        for(int i = 1; i <=2*n; i++)
        {
             dp[i][i]=a[i];
            for(int j=i+1;j<=2*n;j++)
            {
                if(a[j]>dp[i][j-1])
                    dp[i][j]=a[j];
                else
                    dp[i][j]=dp[i][j-1];
            }
        }
        int m;
        scanf("%d", &m);
        int L, R;
        printf("Case #%d:\n",++sum);
        for(int i=1;i<=m;i++)
        {
            int q,w;
            scanf("%d%d",&q,&w);
            if(w<q)
                w=w+n;
            printf("%d\n",dp[q][w]);
        }
        puts("");
    }
    return 0;
}

 

FZU1862(线段树 或者 DP)

标签:

原文地址:http://www.cnblogs.com/ZP-Better/p/4722400.html

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