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;
    }
  • 相关阅读:
    元组的魔法
    列表的魔法
    基础知识
    Pycharm常用快捷键
    django-debug-toolbar
    char 与 varchar 的区别
    Python试题(web篇)
    博客园样式
    网络编程部分试题
    python复习基础题目
  • 原文地址:https://www.cnblogs.com/ZP-Better/p/4722400.html
Copyright © 2011-2022 走看看