• UESTC_秋实大哥下棋 2015 UESTC Training for Data Structures<Problem I>


    I - 秋实大哥下棋

    Time Limit: 3000/1000MS (Java/Others)     Memory Limit: 65535/65535KB (Java/Others)
     

    胜负胸中料已明,又从堂上出奇兵。秋实大哥是一个下棋好手,独孤求败的他觉得下棋已经无法满足他了,他开始研究一种新的玩法。

    在一个n×m的棋盘上,放置了k个车,并且他在棋盘上标出了q个矩形,表示矩形内部是战略要地。

    秋实大哥要求一个矩形内的每一个格子,都至少能被一辆在矩形内的车攻击到,那么这个矩形就是被完整保护的。

    现在秋实大哥想知道每一个矩形是否被完整保护。

    Input

    第一行包含四个整数nmkq,表示棋盘的大小,车的数量以及矩形的数量。

    接来下k行,每行包含两个整数xy,表示有一辆车位于从左往右第x列,从下往上第y行。

    接下来q行,每行包含四个整数x1y1x2y2,表示一个矩形的左下角和右上角坐标。

    1nm1051kq21051x1x21051y1y21051x1051y105

    Output

    输出q行,对于每一次询问,这个矩形若被完整保护了输出"YES",否则输出"NO"。

    Sample input and output

    Sample InputSample Output
    4 3 3 3
    1 1
    3 2
    2 3
    2 3 2 3
    2 1 3 3
    1 2 2 3
    YES
    YES
    NO

    Hint

    样例的图形如下:

    title

    解题报告

    1.如果一个矩形能被完整保护,肯定在矩形的宽 or 长上的车的投影是一段连续的曲线且全部被覆盖.

    2.首先先给矩形排个序(按照X2的大小),还有车(X坐标)

    3.之后我们先考虑这些矩形能否在Y方向达成(被覆盖),注意到X,Y的范围皆为1e5,所以不必采用离散化,从左往右边扫,遇到车就把它所对的Y的方向线段加上一个值val.

    注意到这个加的值是必须考究的,首先我们想因为矩形的X2坐标是递增的,一个在前面的车在Y方向的效果是必须被后面所抵消的(很显然,前面车对Y方向的影响是没有用的,因为前面的车很可能已经在后面的矩形外了)

    因此我们必须维护这个车在Y方向投影值的max,有了这个还不够,我们还不知道这个val值如何计算,才能使得我们能快速计算这个矩形的Y方向被覆盖(注意到很有可能这个线段

    上的某一个部分是前面的车所产生的。。因此为了判断正确,我们必须设计好这个val值)

    4.

    以下为例子: ( x为车 )

     

    3 . . . x .

    2 x . . . .

    1 . . . . . 

    0 1 2 3 4 5

     

    我们考虑左下角坐标为(2,2) ,右上角坐标为(4,3) 的矩形,我们从左往右扫

    首先遇到了车(1,2),我们给Y方向的(2,2)加上一个值 value1;

    之后我们扫到了另外一个车和矩形,那么我们该处理谁呢?,显然是车

    该车的坐标为(4,3),我们给Y方向的(3,3)加上一个值 value2;

    之后扫到矩形的右边,矩形的Y方向为(2,3),我们在(2,3)方向的值为value1与value2..,那么如何才能确定呢。。。

    用X值!,每个方向的投影val值为这个车的X值,并且维护这个最大值,这样我们就可以判断了。why?

    当我们判断[L1,L2]上时,我们只查询这里面的最小值,如果这里面的最小值小于了矩形的X1,那么这个矩形肯定在Y方向没法被完全保护..

     

    至此,就解决了本题. 

    #include <iostream>
    #include <cstring>
    #include <cstdio>
    #include <algorithm>
    
    
    using namespace std;
    const int maxn = 2e5 + 5000;
    int n,m,k,q;
    typedef struct Node
    {
      int l,r,min;    
    };
    
    typedef struct Area
    {
      int x1,x2,y1,y2,id;
      friend bool operator < (const Area&a,const Area& b)
      {
           return a.x2 < b.x2;
      }
    };
    
    typedef struct Point
    {
      int x,y;
      friend bool operator < (const Point &a,const Point & b)
       {
             return a.x < b.x;
       }
    }; //
    
    bool protect[maxn]; //矩形保护 
    Node  tree[4*maxn];
    Area  s[maxn];
    Point p[maxn];
    
    void push_up(int cur)
    {
       tree[cur].min = min(tree[2*cur].min , tree[2*cur+1].min );
    }
    // 把点pos的权值设置为v(取较大) 
    void updata(int pos,int v,int cur)
    {
      int l = tree[cur].l , r = tree[cur].r; 
      if (l == r)
       {
             tree[cur].min = max(tree[cur].min,v);
       }
      else
       {
             int mid = l + (r-l)/2;
             if (mid >= pos)
              updata(pos,v,2*cur);
             else
              updata(pos,v,2*cur+1);
             push_up(cur);
       }
    }
    
    int query(int ql,int qr,int cur)
    {
      int l = tree[cur].l , r = tree[cur].r;
      if (ql <= l && qr >= r)
       return tree[cur].min;
      else
       {
             int mid = l + (r-l)/2;
             int res = 1 << 28;
             if (mid >= ql)
              res = min(res,query(ql,qr,2*cur));
             if (mid < qr)
              res = min(res,query(ql,qr,2*cur+1));
             return res;
       }
    }
    
    void build_tree(int cur,int l ,int r)
    {
       tree[cur].l = l , tree[cur].r = r , tree[cur].min = -1;
       if (r > l)
        {
           int mid = l + (r-l)/2;
           build_tree(2*cur,l,mid);
           build_tree(2*cur+1,mid+1,r);
        }
       
    }
    
    
    int main(int argc,char *argv[])
    {
      scanf("%d%d%d%d",&n,&m,&k,&q);
      build_tree(1,1,max(n,m)+50);
      for(int i = 0 ; i < k ; ++ i)
       {
             int x,y;
             scanf("%d%d",&x,&y);
             p[i].x = x , p[i].y = y;
       }
      memset(protect,false,sizeof(protect));
      for (int i = 0 ; i < q ; ++ i)
       {
             scanf("%d%d%d%d",&s[i].x1,&s[i].y1,&s[i].x2,&s[i].y2);
             s[i].id = i;
       }
      sort(p,p+k);
      sort(s,s+q);
      int k1 = 0 , k2 = 0 ; // 记录目前在线右边边的车,矩形 
      for(int i = 1 ; i <= n ; ++ i)  //扫描线 
       {
             while(k1 < k && p[k1].x <= i) // 车更新
              {
                   updata(p[k1].y,p[k1].x,1);
                   k1++;
           }
             while(k2 < q && s[k2].x2 <= i) // 矩形更新 
              {
                    int minx = query(s[k2].y1,s[k2].y2,1);
                    if (minx >= s[k2].x1 && minx <= s[k2].x2)
                         protect[s[k2].id] = true;
              k2++;
           }
       }
      build_tree(1,1,max(n,m)+50); //reset_tree
      //翻转
      for(int i = 0 ; i < k ; ++ i)
       swap(p[i].x ,p[i].y);
      for(int i = 0 ; i < q; ++ i)
       {
             swap(s[i].x1,s[i].y1);
             swap(s[i].x2,s[i].y2);
       }
      sort(p,p+k);
      sort(s,s+q);
      k1 = k2 = 0;
      for(int i = 1 ; i <= m ; ++ i)  //扫描线 
       {
             while(k1 < k && p[k1].x <= i) // 车更新 
              {
                    updata(p[k1].y,p[k1].x,1);
                    k1++;
           }
             while(k2 < q && s[k2].x2 <= i) // 矩形更新 
              {
                    int minx = query(s[k2].y1,s[k2].y2,1);
                    if (minx >= s[k2].x1 && minx <= s[k2].x2)
                protect[s[k2].id] = true;
              k2++;
           }
       }
      for(int i = 0 ; i < q ; ++ i)
       if (protect[i])
        printf("YES
    ");
       else
        printf("NO
    ");
      return 0;
    }
    No Pain , No Gain.
  • 相关阅读:
    Django 初试水(一)
    自己动手系列----使用数组实现一个简单的Set
    自己动手系列----使用数组实现一个简单的Map
    DB2中的MQT优化机制详解和实践
    Airy Memory 内存清理 + 注册码
    eclipse 工具翻译插件安装
    用sysdba登录oracle 11g数据库时遇到已连接到空闲例程 ora-013113
    Firewall 防火墙规则
    未找到段的定义
    ORACLE 锁表的解决方法 ORA-00054
  • 原文地址:https://www.cnblogs.com/Xiper/p/4470218.html
Copyright © 2020-2023  润新知