HDU 4052 Adding New Machine (线段树+离散化)
2016-05-03 16:14
525 查看
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4052
初始给你w*h的矩阵,给你n个矩形(互不相交),按这些矩形尺寸把初始的矩形扣掉,形成一个新的'矩形'。然后给你1*m大小的矩形,问这个矩形在新'矩形'中有多少种放法。
一开始没想法==,然后看了看题解,说是线段树做的。
要是m为1的话,那答案就是剩下的面积了。
不为1的话,可以把n个矩形的面积扩展一下(我是向右扩展),比如x1 y1 x2 y2 的矩形扣掉,就相当于x1 y1 x2+m-1 y2的地方扣掉了,这种是x轴的情况。那么y轴的情况就是x1 y1 x2 y2+m-1。最左边也要扣掉,比如x轴就是0 0 m - 1 h。所以最后就是算剩下的面积了。(我的方法比较笨,就是x轴一个线段树扫一下,y轴一个线段树扫一下)
初始给你w*h的矩阵,给你n个矩形(互不相交),按这些矩形尺寸把初始的矩形扣掉,形成一个新的'矩形'。然后给你1*m大小的矩形,问这个矩形在新'矩形'中有多少种放法。
一开始没想法==,然后看了看题解,说是线段树做的。
要是m为1的话,那答案就是剩下的面积了。
不为1的话,可以把n个矩形的面积扩展一下(我是向右扩展),比如x1 y1 x2 y2 的矩形扣掉,就相当于x1 y1 x2+m-1 y2的地方扣掉了,这种是x轴的情况。那么y轴的情况就是x1 y1 x2 y2+m-1。最左边也要扣掉,比如x轴就是0 0 m - 1 h。所以最后就是算剩下的面积了。(我的方法比较笨,就是x轴一个线段树扫一下,y轴一个线段树扫一下)
#include <iostream> #include <cstring> #include <cstdio> #include <algorithm> #include <map> using namespace std; const int MAXN = 1e5 + 10; typedef long long LL; LL fab(LL a) { return (a > 0 ? a : -a); } struct data { int ll , rr , flag , l , r , h; bool operator <(const data &cmp) const { return h < cmp.h; } }line1[MAXN] , line2[MAXN]; struct segtree { LL val; int l , r , add; }T1[MAXN * 3] , T2[MAXN * 3]; LL x[MAXN] , y[MAXN]; map <int , int> mp1 , mp2; int f1 , f2; inline void add1(LL num) { if(!mp1[num]) { x[++f1] = num; mp1[num] = 1; } } inline void add2(LL num) { if(!mp2[num]) { y[++f2] = num; mp2[num] = 1; } } void pushupx(int p) { if(T1[p].add) { T1[p].val = x[T1[p].r] - x[T1[p].l]; } else if(T1[p].r - T1[p].l == 1) { T1[p].val = 0; } else { T1[p].val = T1[p << 1].val + T1[(p << 1)|1].val; } } void pushupy(int p) { if(T2[p].add) { T2[p].val = y[T2[p].r] - y[T2[p].l]; } else if(T2[p].r - T2[p].l == 1) { T2[p].val = 0; } else { T2[p].val = T2[p << 1].val + T2[(p << 1)|1].val; } } void buildx(int p , int l , int r) { int mid = (l + r) >> 1; T1[p].l = l , T1[p].r = r , T1[p].val = T1[p].add = 0; if(r - l == 1) { return ; } buildx(p << 1 , l , mid); buildx((p << 1)|1 , mid , r); } void buildy(int p , int l , int r) { int mid = (l + r) >> 1; T2[p].l = l , T2[p].r = r , T2[p].val = T2[p].add = 0; if(r - l == 1) { return ; } buildy(p << 1 , l , mid); buildy((p << 1)|1 , mid , r); } void updatex(int p , int l , int r , int add) { int mid = (T1[p].l + T1[p].r) >> 1; if(T1[p].l == l && T1[p].r == r) { T1[p].add += add; pushupx(p); return ; } if(r <= mid) { updatex(p << 1 , l , r , add); } else if(l >= mid) { updatex((p << 1)|1 , l , r , add); } else { updatex(p << 1 , l , mid , add); updatex((p << 1)|1 , mid , r , add); } pushupx(p); } void updatey(int p , int l , int r , int add) { int mid = (T2[p].l + T2[p].r) >> 1; if(T2[p].l == l && T2[p].r == r) { T2[p].add += add; pushupy(p); return ; } if(r <= mid) { updatey(p << 1 , l , r , add); } else if(l >= mid) { updatey((p << 1)|1 , l , r , add); } else { updatey(p << 1 , l , mid , add); updatey((p << 1)|1 , mid , r , add); } pushupy(p); } int main() { LL w , h , n , m , x1 , x2 , y1 , y2; while(~scanf("%lld %lld %lld %lld" , &w , &h , &n , &m)) { mp1.clear(); mp2.clear(); f1 = f2 = 0; if(m == 1) { LL sum = 0; while(n--) { scanf("%lld %lld %lld %lld" , &x1 , &y1 , &x2 , &y2); sum += (fab(x1 - x2) + 1) * (fab(y1 - y2) + 1); } printf("%lld\n" , h * w - sum); continue; } for(int i = 0 ; i < n ; i++) { scanf("%lld %lld %lld %lld" , &x1 , &y1 , &x2 , &y2); x1-- , y1--; int ls = i << 1 , rs = (i << 1)|1; line1[ls].l = x1 , line1[ls].r = min(w , x2 + m - 1) , line1[ls].h = y1 , line1[ls].flag = 1; line1[rs].l = x1 , line1[rs].r = line1[ls].r , line1[rs].h = y2 , line1[rs].flag = -1; line2[ls].l = y1 , line2[ls].r = min(h , y2 + m - 1) , line2[ls].h = x1 , line2[ls].flag = 1; line2[rs].l = y1 , line2[rs].r = line2[ls].r , line2[rs].h = x2 , line2[rs].flag = -1; add1(line1[ls].l); add1(line1[ls].r); add1(line1[rs].l); add1(line1[rs].r); add2(line2[ls].l); add2(line2[ls].r); add2(line2[rs].l); add2(line2[rs].r); } int ls = n << 1 , rs = (n << 1)|1 , f = ((n << 1)|1) + 1; line1[ls].l = 0 , line1[ls].r = m - 1 , line1[ls].h = 0 , line1[ls].flag = 1; line1[rs].l = 0 , line1[rs].r = m - 1 , line1[rs].h = h , line1[rs].flag = -1; line2[ls].l = 0 , line2[ls].r = m - 1 , line2[ls].h = 0 , line2[ls].flag = 1; line2[rs].l = 0 , line2[rs].r = m - 1 , line2[rs].h = w , line2[rs].flag = -1; add1(line1[ls].l); add1(line1[ls].r); add1(line1[rs].l); add1(line1[rs].r); add2(line2[ls].l); add2(line2[ls].r); add2(line2[rs].l); add2(line2[rs].r); sort(line1 , line1 + f); sort(line2 , line2 + f); sort(x + 1 , x + f1 + 1); sort(y + 1 , y + f2 + 1); for(int i = 0 ; i < f ; i++) { line1[i].ll = lower_bound(x + 1 , x + f1 + 1 , line1[i].l) - x; line1[i].rr = lower_bound(x + 1 , x + f1 + 1 , line1[i].r) - x; line2[i].ll = lower_bound(y + 1 , y + f2 + 1 , line2[i].l) - y; line2[i].rr = lower_bound(y + 1 , y + f2 + 1 , line2[i].r) - y; } LL res1 = 0 , res2 = 0; buildx(1 , 1 , f1); buildy(1 , 1 , f2); updatex(1 , line1[0].ll , line1[0].rr , line1[0].flag); updatey(1 , line2[0].ll , line2[0].rr , line2[0].flag); for(int i = 1 ; i < f ; i++) { res1 += (line1[i].h - line1[i - 1].h) * T1[1].val; res2 += (line2[i].h - line2[i - 1].h) * T2[1].val; updatex(1 , line1[i].ll , line1[i].rr , line1[i].flag); updatey(1 , line2[i].ll , line2[i].rr , line2[i].flag); } printf("%lld\n" , h * w * 2 - res1 - res2); } }
相关文章推荐
- 解决MySQL5.6出现"Using a password on the command line interface..."
- GDOI2016总结
- Android 分享到微信6.0后好友、朋友圈
- 验证码生成类
- 【转】如何分析解决Android ANR
- 2016年5月02日 - 精华
- axis2客户端调用服务器
- 练习三 1001
- 【VS开发】关于在CFormView中实现CListCtrl控件的注意事项
- MySQL 多表连接查询
- 第12期【江山代有才人出】5月刊
- redis的aof持久化深入解析
- Fast RCNN 训练自己数据集 (1编译配置)
- 重要的东西
- openwrt创建软件包
- JSTL 字符串长度判断并截取
- Java_Regex
- Linux上程序执行的入口--main(int argc, char *argv[])
- 运营内部PPT分享:通俗易懂聊运营
- Spark性能优化指南——基础篇