hdu - 6681 Rikka with Cake 线段树
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6681
题意:给定一个左下顶点为,右上顶点为
的矩形,然后给你k条射线,每条射线的起点及方向(上下左右)都已知,射线的起点都位于矩形内,不包括矩形边界,且每条射线间不会有重叠,求矩形被分割成多少块。
思路:由于是射线,因此容易知道每一次射线的相交都会使答案+1,考虑用线段树求解。按照起始点的x坐标对射线排序,对y轴坐标离散化,从左往右更新,遇到向上或者向下的射线,对线段树上的对应区间+1,遇到向左的射线,对线段树进行单点查询,答案加上查询结果。初始化线段树后,从右往左更新,处理向右的射线,其余不变。处理完毕后即可得到答案。由于只需要线段树中叶节点的值,因此可以不用pushUp函数。
代码:
#include <iostream>
#include <cstring>
#include <algorithm>using namespace std;const int N = 1e5+10;struct line
{int x, y;char oper;bool operator <(const line &A) const{return x < A.x;}
}Line[N];int x[N], y[N];
int sum[N<<2], lazy[N<<2];void pushDown(int rt)
{if(!lazy[rt]) return ;sum[rt<<1] += lazy[rt];sum[rt<<1|1] += lazy[rt];lazy[rt<<1] += lazy[rt];lazy[rt<<1|1] += lazy[rt];lazy[rt] = 0;
}void update(int L,int R,int l,int r,int rt)
{if(L <= l && r <= R){lazy[rt] += 1;sum[rt] += 1;return ;}int m = (l+r)>>1;pushDown(rt);if(L <= m) update(L,R,l,m,rt<<1);if(m < R) update(L,R,m+1,r,rt<<1|1);
}int query(int L,int l,int r,int rt)
{if(l == r)return sum[rt];int m = (l+r)>>1, ans = 0;pushDown(rt);if(L <= m) ans += query(L,l,m,rt<<1);else ans += query(L,m+1,r,rt<<1|1);return ans;
}int main()
{ios::sync_with_stdio(false);cin.tie(0), cout.tie(0);int T, n, m, M;long long ans = 0;cin>>T;while(T--){ans = 0;cin>>n>>m>>M;memset(sum, 0, sizeof sum);memset(lazy, 0, sizeof lazy);for(int i = 1; i <= M; ++i){cin>>Line[i].x>>Line[i].y>>Line[i].oper;x[i] = Line[i].x, y[i] = Line[i].y;}sort(y+1,y+M+1);int posy = unique(y+1,y+M+1)-y-1;sort(Line+1,Line+M+1);for(int i = 1; i <= M; ++i){int t = lower_bound(y+1,y+posy+1,Line[i].y)-y;if(Line[i].oper == 'U'){update(t,posy,1,posy,1);}else if(Line[i].oper == 'D'){update(1,t,1,posy,1);}else if(Line[i].oper == 'L'){ans += query(t,1,posy,1);}}memset(sum, 0, sizeof sum);memset(lazy, 0, sizeof lazy);for(int i = M; i >= 1; --i){int t = lower_bound(y+1,y+posy+1,Line[i].y)-y;if(Line[i].oper == 'U'){update(t,posy,1,posy,1);}else if(Line[i].oper == 'D'){update(1,t,1,posy,1);}else if(Line[i].oper == 'R'){ans += query(t,1,posy,1);}}cout<<ans+1<<'\n';}return 0;
}
hdu - 6681 Rikka with Cake 线段树相关推荐
- HDU 6681 Rikka with Cake(扫描线、动态开点线段树)
http://acm.hdu.edu.cn/showproblem.php?pid=6681 题意 在矩形区域内有k条射线,问这些射线将矩形分成了多少区域 题解 容易发现答案为所有射线交点个数+1. ...
- HDU 6089 Rikka with Terrorist (线段树)
题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=6089 题解 这波强行维护搞得我很懵逼... 扫描线,只考虑每个点能走到左上方(不包括正上方,但包括正左 ...
- HDU - 6681 Rikka with Cake
Rikka with Cake Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 524288/524288 K (Java/Others) P ...
- hdu 6681 Rikka with Cake(扫描线)
题意:给你一个n*m的的矩形框 现在又k条射线 问这个矩形框会被分为多少个区域 思路:之前的想法是枚举边界然后线段树扫一遍计算一下矩形个数 复杂度果断不行 后面发现其实答案就是交点数+1 然后就用线段 ...
- HDU 6681 Rikka with Cake (可持久化线段树)
题目:http://acm.hdu.edu.cn/showproblem.php?pid=6681 题意:一个n*m的矩形蛋糕,每次给一个点(x, y)和方向dir确定一条切的线,问最后把蛋糕分成了几 ...
- HDU 5828 Rikka with Sequence (线段树+剪枝优化)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5828 给你n个数,三种操作.操作1是将l到r之间的数都加上x:操作2是将l到r之间的数都开方:操作3是 ...
- HDU 1166 敌兵布阵(线段树:点更新,区间求和)
HDU 1166 敌兵布阵(线段树:点更新,区间求和) http://acm.hdu.edu.cn/showproblem.php?pid=1166 题意: 给你n个整数,然后给你多条命令,每条命令如 ...
- HDU 3016 Man Down (线段树+dp)
HDU 3016 Man Down (线段树+dp) Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Ja ...
- 2019CCPC网络赛 1002 HDU 6703(权值线段树)
2019CCPC网络赛 1002 HDU 6703(权值线段树) 思路:用权值线段树存题目给的数据后,2操作就是求权值线段树中大于等于k的部分中,靠近左端点的第一个大于r的值(这个求出来的只是原序列中 ...
最新文章
- Proc-fs 编程
- Zookeeper高级
- 写一副对子_挥毫泼墨写春联 西安街头年味分外浓
- 成功解决ValueError: DataFrame.dtypes for label must be int, float or bool
- Remove Duplicates from Sorted List 去除链表中重复值节点
- Spring security+jwt服务鉴权完整代码
- Spring——Spring工具类
- java.util.concurrent 编程范例
- LeetCode 103. 二叉树的锯齿形层次遍历(Binary Tree Zigzag Level Order Traversal)
- WebDevHelper -- RESTful服务和Ajax开发时的利器
- apqp过程流程图及编写规则_APQP各阶段输入及输出流程图(含输出资料清单)
- 华纳云:美国高防服务器的防火墙介绍
- 赶路人-----李小晓
- 游久刘亮:从最具草莽气质的80后 到上市公司CEO
- Java 实现简单的发红包代码
- 计算机考试去底纹,2017职称计算机考试Word 2003知识点:段落添加边框和底纹
- Linux在加载模块时报insmod: error inserting xxx.ko -1 File exists这个错
- 秉火429笔记之十二 看门狗
- cmd操作MySQL 范式、单表查询(日记 day 3)
- 中山大学计算机考研专业课考什么,2017年中山大学0812计算机科学与技术考研专业目录及考试科目...