zoukankan      html  css  js  c++  java
  • bzoj1067——SCOI2007降雨量(线段树,细节题)

    题目描述
    我们常常会说这样的话:“X年是自Y年以来降雨量最多的”。它的含义是X年的降雨量不超过Y年,且对于任意(Y<Z<X),Z年的降雨量严格小于X年。例如2002,2003,2004和2005年的降雨量分别为4920,5901,2832和3890,则可以说“2005年是自2003年以来最多的”,但不能说“2005年是自2002年以来最多的”由于有些年份的降雨量未知,有的说法是可能正确也可以不正确的。

    输入输出格式

    输入格式:
    输入仅一行包含一个正整数n,为已知的数据。以下n行每行两个整数(yi)(ri),为年份和降雨量,按照年份从小到大排列,即(yi<yi+1)。下一行包含一个正整数m,为询问的次数。以下m行每行包含两个数Y和X,即询问“X年是自Y年以来降雨量最多的。”这句话是必真、必假还是“有可能”。

    输出格式:
    对于每一个询问,输出true,false或者maybe。

    简单来说!对于一个询问来说(x,y),我们需要满足(xge y>z 其中zin[x+1,y-1])

    一眼看过去QwQ
    这个题难道不是区间维护最大值,不就OK了吗?
    一写,发现完美gg!!

    进入正题:

    首先我们发现年份是非常大的,所以需要将离散化,同时又方便我们统计有没有未知的年份(maybe)

    那么我们就从小到大依次将年份标号为(1 - n),然后如果当前的年份比前一个年份大1以上,那么就将给他赋一个1的权值

    那么我们统计两个年份之间有没有未知的年的时候,我们需要求一个区间和,就可以得知了

    接下来是处理询问,首先我们要知道询问种给定的两个年份不一定是都知道的
    那么我们应该怎么判断这个年份是不是知道的呢?

    只需要开一个数组,记录所有出现的年份,然后(lower_bound)一下,看一下和它本身一不一样就行了

    int getpos(int x)
    {
       if (x<ss[1]) return ss[1];
       if (x>ss[n]) return ss[n];
       return ss[lower_bound(ss,ss+1+n,x)-ss];
    }
    

    所以需要分类讨论:

    当$x!=getpos(x) 且 y!=getpos(y) (的时候,一定是)maybe$

    当$x==getpos(x) 且 y!=getpos(y) $的时候,我们需要把y跳到第一个已知的年(就是比他小的最大的)

    if (y>ss[n]) y=ss[n];
           else
      	     y=ss[lower_bound(ss,ss+1+n,y)-ss-1];
    

    然后比较中间的数,是否都小于x,如果存在大于等于的x的年份,那一定是(false)否则就是(maybe)

    (x!=getpos(x) 且 y==getpos(y))的时候,同理

    (x==getpos(x) 且 y==getpos(y))的时候

    我们就是要满足(xge y>z 其中zin[x+1,y-1])就可以,那么求一个中间区间的最大值,然后比较一下就可以
    如果中间区间的query不等于区间长度,那就是maybe
    我建议,就是先判断(false)接着判断(true)else就是(maybe)

    一些细节之间看代码吧

    上代码

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    #include<cstdlib>
    #include<queue>
    #include<map>
    #include<vector>
    
    using namespace std;
    
    inline int read()
    {
      int x=0,f=1;char ch=getchar();
      while (!isdigit(ch)) {if (ch=='-') f=-1;ch=getchar();}
      while (isdigit(ch)) {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
      return x*f;
    }
    
    const int maxn = 300010;
    
    struct Node{
        int mx,mn;
        int sum;
    };
    
    Node f[4*maxn];
    int n,m;
    int a[maxn];
    int c[maxn];
    
    void up(int root)
    {
        f[root].mx=max(f[2*root].mx,f[2*root+1].mx);
        f[root].mn=min(f[2*root].mn,f[2*root+1].mn);
        f[root].sum=f[2*root].sum+f[2*root+1].sum;
    }
    
    void build(int root,int l,int r)	
    {
        if (l==r)
        {
            f[root].mn=f[root].mx=a[l];
            f[root].sum=c[l];
            return;
        }
        int mid = (l+r) >> 1;
        build(2*root,l,mid);
        build(2*root+1,mid+1,r);
        up(root);
    }
    
    int querymax(int root,int l,int r,int x,int y)
    {
        if (l>r || x>y) return -2e9;
        if (x<=l && r<=y)
        {
            return f[root].mx;
        }
        int mid = (l+r) >> 1;
        int ans = -2e9;
        if (x<=mid) ans=max(ans,querymax(2*root,l,mid,x,y));
        if (y>mid) ans=max(ans,querymax(2*root+1,mid+1,r,x,y));
        return ans;
    }
    
    int querysum(int root,int l,int r,int x,int y)
    {
        if (l>r || x>y) return 0;
       if (x<=l && r<=y)
       {
         return f[root].sum;
       }
       int mid = (l+r) >> 1;
       int ans = 0;
       if (x<=mid) ans+=querysum(2*root,l,mid,x,y);
       if (y>mid) ans+=querysum(2*root+1,mid+1,r,x,y);
       return ans;
    }
    
    int front;
    int ss[maxn];
    
    int getpos(int x)
    {
       if (x<ss[1]) return ss[1];
       if (x>ss[n]) return ss[n];
       return ss[lower_bound(ss,ss+1+n,x)-ss];
    }
    
    int get(int x)
    {
        if (x<ss[1]) return 1;
        if (x>ss[n]) return n;
        return lower_bound(ss,ss+1+n,x)-ss;
    }
    
    int main()
    {
      scanf("%d",&n);
      c[1]=1;
      for (int i=1;i<=n;i++)
      {
      	  int x,y;
          scanf("%d",&x);
          scanf("%d",&a[i]);
          if (i!=1 && x-front==1) c[i]=1;
          ss[i]=x;
          front=x;
      } 
      ss[++n]=2e9; ss[0]=-2e9;
      build(1,1,n);
     
     
      scanf("%d",&m);
     // cout<<querymax(1,1,n,2,4)<<endl;
      for (int i=1;i<=m;i++)
      {
      	 int x,y;
      	 x=read(),y=read();
      	 if (x!=getpos(x) && y!=getpos(y))
      	 {
      	 	printf("maybe
    ");
      	 	continue;
         }
         if (x!=getpos(x))
         {
      	   x=getpos(x);
      	   int a1=querymax(1,1,n,get(x),get(y)-1);
      	   int cnt = a[get(y)];
      	   if (a1>=cnt) printf("false
    ");
      	   else printf("maybe
    ");
      	   continue;
        }
        if (y!=getpos(y))
         {
           if (y>ss[n]) y=ss[n];
           else
      	     y=ss[lower_bound(ss,ss+1+n,y)-ss-1];
      	   int a1=querymax(1,1,n,get(x)+1,lower_bound(ss,ss+1+n,y)-ss);
      	   //cout<<a1<<endl;
      	   int cnt = a[get(x)];
      	   if (a1>=cnt) printf("false
    ");
      	   else printf("maybe
    ");
      	   continue; 
        }
        int l=get(x)+1,r=get(y);
        int cnt = a[get(y)];
        int cnt1=a[get(x)]; 
      	int a1=querymax(1,1,n,get(x)+1,get(y)-1);
      	int a3=querysum(1,1,n,get(x)+1,get(y));
      	if (a1>=cnt || cnt>cnt1) printf("false
    ");
      	else if (a1<cnt && r-l+1==a3 && cnt<=cnt1) printf("true
    ");
      	else printf("maybe
    ");
      }
      return 0;
    }
    
    
  • 相关阅读:
    现代软件工程的构建之法
    How do I Check for Duplicate Items in a ListView?
    (转)aspxgridview记录的批量修改
    vs2010简体中文旗舰版智能感知,中文提示,英文提示变化的问题
    (转)怎样成为一名Android开发者
    It’s Not Too Late to Learn How to Code
    (转)手机屏幕VGA QVGA HVGA WVGA区别
    (转)CodeSmithSchemaExplorer类结构详细介绍
    (转)C#控件命名规范
    DataReader 绑定DataGridView的方式
  • 原文地址:https://www.cnblogs.com/yimmortal/p/10160729.html
Copyright © 2011-2022 走看看