zoukankan      html  css  js  c++  java
  • FZU1862(线段树 或者 DP)

    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:
    ", cas++);
            for(int j = 0; j < m; j++)
            {
                scanf("%d%d", &a, &b);
                if(b < a)
                    b = b + n;
                printf("%d
    ", 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:
    ",++sum);
            for(int i=1;i<=m;i++)
            {
                int q,w;
                scanf("%d%d",&q,&w);
                if(w<q)
                    w=w+n;
                printf("%d
    ",dp[q][w]);
            }
            puts("");
        }
        return 0;
    }
  • 相关阅读:
    java_hibernate 框架4
    java_hibernate 框架3
    java 基础 动态代理
    java_hibernate 框架2
    nginx配置反向代理实现负载均衡 小记
    mysql报错2059
    docker安装php容器小记
    docker安装nginx容器小记
    linux php添加pdo_mysql扩展
    linux php添加openssl扩展
  • 原文地址:https://www.cnblogs.com/ZP-Better/p/4722400.html
Copyright © 2011-2022 走看看