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

E - 秋实大哥与家

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

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

所以他买了很多家具。

秋实大哥的家可以看成一个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\n",a[i].getx(),a[i].y1 , a[i].y2);
110          }
111         else
112          printf("出边 , x is %d , y1 is %d, y2 is %d\n",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\n",b[i].y1,b[i].x1,b[i].x2 );
123         } 
124        else
125         {
126             printf("出边 , y is %d ,left is %d,right is %d\n",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\n",ans/2);
204   else
205    printf("%lld\n",ans);
206   return 0;
207 }

 

转载于:https://www.cnblogs.com/Xiper/p/4470211.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值