• UESTC_秋实大哥与家 2015 UESTC Training for Data Structures<Problem E>


    E - 秋实大哥与家

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

    秋实大哥是一个顾家的男人,他认为人生就是旅途,不管我们漂到哪,最终还是会回到温暖的地方——家。

    所以他买了很多家具。

    秋实大哥的家可以看成一个W×H的矩阵,每一件家具可以看成一个矩形,他们放置在秋实大哥的家里,相互之间没有重叠。

    现在秋实大哥购置了一个新的大小为1×M的家具,秋实大哥想知道他有多少种方式来安放这个家具。

    Input

    第一行包含四个整数WHnM,表示秋实大哥家的大小为W×H,现在已有n个家具,新购置的家具大小为1×M

    接下来n行,每行包含4个整数x1y1x2y2,分别表示这个家具左下角的坐标和右上角的坐标。

    1nHWM1000001x1x2W1y1y2H

    Output

    输出一行包含一个整数,表示有多少种方案可以来放置秋实大哥的新家具,要求不能跟原有的家具重叠,也不能超出家的范围。

    Sample input and output

    Sample InputSample Output
    3 3 1 2
    2 2 2 2
    8

    解题报告:

    注意到所有的家具是1 x m的,不外乎横放与竖放,我们先考虑横放,对于每个矩形,其左端线坐标为x1,右端线坐标为x2.

    那么下列这些点肯定无法放置的(以这些点为最左端放置)

     (X1-m+1,x2) , y ∈ [y1,y2]

    那么问题就好解决了,每读入一个矩形,将其线延长,之后算不合法的面积,用总面积减去不合法的面积即为方案数.

    竖放的道理一样,这里不再阐述.注意到 m = 1的情况,横 / 竖是一样的

      1 #include <iostream>
      2 #include <algorithm>
      3 #include <cstring>
      4 #include <cstdio>
      5 typedef long long ll;
      6 using namespace std;
      7 const int maxn = 6e5 + 50;
      8 const int maxtreesize = 6e5 + 50;
      9 int w,h,n,m,size=0;
     10 
     11 typedef struct node
     12 {
     13 int l,r,cover,sum;
     14 };
     15 
     16 node tree[maxtreesize];
     17 
     18 void push_up(int cur)
     19 {
     20    int lc = 2*cur;
     21    int rc = 2*cur+1;
     22    if (tree[cur].cover)
     23     tree[cur].sum = tree[cur].r - tree[cur].l;
     24    else if(tree[cur].l == tree[cur].r ) // 叶子 
     25     tree[cur].sum = 0;
     26    else
     27     {
     28        if (tree[lc].cover && tree[rc].cover )   // Updata Father
     29         tree[cur].sum = tree[lc].sum + tree[rc].sum;
     30        else
     31         tree[cur].sum = tree[lc].sum + tree[rc].sum;
     32     }
     33     
     34 }
     35 
     36 
     37 void updata(int ql,int qr,int v,int cur)
     38 {
     39   int lc = 2*cur , rc = 2*cur + 1 , l = tree[cur].l , r = tree[cur].r;
     40   if (r == l) //
     41    return;
     42   if (l >= ql && r <= qr)
     43    {
     44          tree[cur].cover += v;
     45          push_up(cur);
     46    }
     47   else
     48    {
     49          int mid = l + (r-l)/2;
     50          if (mid > ql)
     51           updata(ql,qr,v,lc);
     52          if (mid < qr)
     53           updata(ql,qr,v,rc);
     54          push_up(cur);
     55    }
     56 }
     57 
     58 void build_tree(int cur,int l,int r)
     59 {
     60     tree[cur].l = l,tree[cur].r = r;
     61     if (r - l > 1 )
     62      {
     63           int mid = l + (r-l)/2;
     64           build_tree(2*cur,l,mid);
     65           build_tree(2*cur+1,mid,r);
     66      }
     67 }
     68 
     69 
     70 typedef struct line
     71 {
     72   int x1,x2,y1,y2;
     73   bool flag; // 0 是入边,1 是出边 
     74   inline int getx()
     75    {
     76          if (flag)
     77           return x2;
     78          else
     79           return x1;
     80    }
     81   inline int gety()
     82    {
     83          if (flag)
     84           return y2;
     85          else
     86           return y1;
     87    }
     88 };
     89 
     90 line a[maxn]; // x 方向上被限制 
     91 line b[maxn]; // y 方向上被限制 
     92 
     93 bool cmp1(line a,line b)
     94 {
     95    return a.getx() < b.getx();
     96 }
     97 
     98 bool cmp2(line a,line b)
     99 {
    100    return a.gety() < b.gety();
    101 }
    102 
    103 void dump__()
    104 {
    105    for(int i = 0 ; i < size ; ++ i)
    106     {
    107         if (a[i].flag == 0)
    108          {
    109              printf("入边 , x is %d , y1 is %d, y2 is %d
    ",a[i].getx(),a[i].y1 , a[i].y2);
    110          }
    111         else
    112          printf("出边 , x is %d , y1 is %d, y2 is %d
    ",a[i].getx(),a[i].y1 , a[i].y2);
    113     }
    114 }
    115 
    116 void dump()
    117 {
    118     for(int i = 0 ; i < size ; ++ i)
    119     {
    120        if (b[i].flag == 0)
    121         {
    122             printf("入边 , y is %d ,left is %d,right is %d
    ",b[i].y1,b[i].x1,b[i].x2 );
    123         } 
    124        else
    125         {
    126             printf("出边 , y is %d ,left is %d,right is %d
    ",b[i].y2,b[i].x1,b[i].x2 );
    127         }
    128     }
    129 }
    130 
    131 ll sall;  //总面积 
    132 
    133 
    134 ll slove1()
    135 {
    136    ll res = 0;
    137    sort(a,a+size,cmp1);
    138    int cur = 1;
    139    updata(a[0].y1,a[0].y2,1,1);
    140    while(cur < size)
    141     {
    142        int dis = a[cur].getx() - a[cur-1].getx();
    143        res += (ll)dis*(ll)tree[1].sum;
    144        if (a[cur].flag & 1) //出边 
    145         updata(a[cur].y1,a[cur].y2,-1,1);
    146        else
    147         updata(a[cur].y1,a[cur].y2,1,1); 
    148        cur++;
    149     } 
    150    return sall - res;
    151 }
    152 
    153 
    154 ll slove2()
    155 {
    156    ll res = 0;
    157    sort(b,b+size,cmp2);
    158    int cur = 1;
    159    updata(b[0].x1,b[0].x2,1,1);
    160    while(cur < size)
    161     {
    162        int dis = b[cur].gety() - b[cur-1].gety();
    163        res += (ll)dis*(ll)tree[1].sum;
    164        if (b[cur].flag & 1) //出边 
    165         updata(b[cur].x1,b[cur].x2,-1,1);
    166        else
    167         updata(b[cur].x1,b[cur].x2,1,1);
    168        cur++;
    169     } 
    170    return sall - res;
    171 }
    172 
    173 int main(int argc,char *argv[])
    174 {
    175   scanf("%d%d%d%d",&w,&h,&n,&m);
    176   memset(tree,0,sizeof(tree));
    177   memset(a,0,sizeof(a));
    178   memset(b,0,sizeof(b));
    179   build_tree(1,0,max(w,h)+4); // Build Tree
    180   sall = (ll)w*(ll)h;
    181   for(int i = 0 ; i < n ; ++ i)
    182    {
    183          int x1,y1,x2,y2,oriy1,orix1;
    184          scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
    185          x1 -- , y1 -- ; //转换为线段式 
    186          orix1 = x1,oriy1 = y1;
    187          x1 = x1-m+1 >= 0 ? x1-m+1 : 0;
    188          y1 = y1-m+1 >= 0 ? y1-m+1 : 0;
    189          a[size].x1 = x1,a[size].x2 = x2,a[size].y1 = oriy1 , a[size].y2 = y2 , a[size].flag = 0;
    190          b[size].x1 = orix1 , b[size].x2 = x2 , b[size].y1 = y1,b[size].y2 = y2 , b[size++].flag = 0;
    191          a[size].x1 = x1,a[size].x2 = x2,a[size].y1 = oriy1 , a[size].y2 = y2 , a[size].flag = 1;
    192          b[size].x1 = orix1 , b[size].x2 = x2 , b[size].y1 = y1,b[size].y2 = y2 , b[size++].flag = 1;
    193    }
    194   ll ans = 0;
    195   a[size].x1 = w-m + 1 >= 0 ? w-m+1 : 0 , a[size].x2 = w , a[size].y1 = 0 , a[size].y2 = h,a[size++].flag = 0;  //添加限制线  
    196   a[size].x1 = w-m + 1 >= 0 ? w-m+1 : 0 , a[size].x2 = w , a[size].y1 = 0 , a[size].y2 = h,a[size++].flag = 1;
    197   ans += slove1();
    198   size -= 2;
    199   b[size].x1 = 0,b[size].x2 = w ,b[size].y1 = h-m+1 >= 0 ? h-m+1 : 0,b[size].y2 = h , b[size++].flag = 0;
    200   b[size].x1 = 0,b[size].x2 = w ,b[size].y1 = h-m+1 >= 0 ? h-m+1 : 0,b[size].y2 = h , b[size++].flag = 1;
    201   ans += slove2();
    202   if (m == 1)
    203    printf("%lld
    ",ans/2);
    204   else
    205    printf("%lld
    ",ans);
    206   return 0;
    207 }
    No Pain , No Gain.
  • 相关阅读:
    学习了一下调色理论
    几个同步软件
    慢性咽炎
    flash行情
    C#创建Windows服务
    .net下 foreach 与 for 的效率比较测试
    HTML服务器控件与Web服务器控件的区别
    c#遍历HashTable
    ASP.NET中Server与Request对象的方法
    .net内存回收与Dispose﹐Close﹐Finalize方法
  • 原文地址:https://www.cnblogs.com/Xiper/p/4470211.html
Copyright © 2020-2023  润新知