题目地址:http://acm.hdu.edu.cn/showproblem.php?pid=6681

题目:


Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 524288/524288 K (Java/Others)

Problem Description

Rikka's birthday is on June 12th. The story of this problem happens on that day.

Today is Rikka's birthday. Yuta prepares a big cake for her: the shape of this cake is a rectangular of n centimeters times m centimeters. With the guidance of a grimoire, Rikka is going to cut the cake.

For simplicity, Rikka firstly builds a Cartesian coordinate system on the cake: the coordinate of the left bottom corner is (0,0) while that of the right top corner is (n,m). There are K instructions on the grimoire: The ith cut is a ray starting from (xi,yi) while the direction is Di. There are four possible directions: L, passes (xi−1,yi); R, passes (xi+1,yi); U, passes (xi,yi+1); D, passes (xi,yi−1).

Take advantage of the infinite power of Tyrant's Eye, Rikka finishes all the instructions quickly. Now she wants to count the number of pieces of the cake. However, since a huge number of cuts have been done, the number of pieces can be very large. Therefore, Rikka wants you to finish this task.

Input

The first line of the input contains a single integer T(1≤T≤100), the number of the test cases.

For each test case, the first line contains three positive integers n,m,K(1≤n,m≤109,1≤K≤105), which represents the shape of the cake and the number of instructions on the grimoire.

Then K lines follow, the ith line contains two integers xi,yi(1≤xi<n,1≤yi<m) and a char Di∈{'L','R','U','D'}, which describes the ith cut.

The input guarantees that there are no more than 5 test cases with K>1000, and no two cuts share the same x coordinate or y coordinate, i.e., ∀1≤i<j≤K, xi≠xj and yi≠yj.

Output

For each test case, output a single line with a single integer, the number of pieces of the cake.

Hint

The left image and the right image show the results of the first and the second test case in the sample input respectively. Clearly, the answer to the first test case is 3while the second one is 5.

Sample Input

2

4 4 3

1 1 U

2 2 L

3 3 L

5 5 4

1 2 R

3 1 U

4 3 L

2 4 D

Sample Output

3

5

解题思路:


重温此题。

题目限制:输入的这点的坐标x,y都互不相同,且不在边界上。

盲猜答案是交点个数+1(严谨证明有些复杂,此处略)。

思路也有些巧妙:

      

将左图转化为右图,当射线方向朝下时,分解成两个新的射线,如右图。

将这些射线按照起点的高度从低到高排列,高度相同时,竖直方向的射线排在前面。

依次处理拍完序后的射线,以右图为例:

当处理到蓝色虚射线时,射线B和射线A和这条蓝色虚射线都有交点,且交点的横坐标时左图C.x,标记C.x;

同理处理到射线D时,它和射线A、B也有交点,交点横坐标都是D.x,标记D.x;

接着处理射线A,射线A上可能对答案有贡献的点的横坐标的范围为[A.x,n-1],所以此时就需要求出[A.x,n-1]被标记的点的数目,添加到最终答案中;

再处理紫色虚射线,它和射线B有交点,交点横坐标为C.x,取消C.x的标记;

最后处理射线B, 射线B上可能对答案有贡献的点的横坐标的范围为[1, B.x],需要求出[1, B.x]内被标记的点数目,添加到答案中。

因为我们在求交点个数的时候只考虑了横坐标,而横坐标的范围比较大,需要把需要用到的横坐标离散化(最多k+2个不同的横坐标)。标记的话可以直接标记1(单点更新),然后区间求和求出交点个数,所以可以用树状数组写,代码短好写。

总体思路:从下到上处理射线,转化后只存在朝上的射线。同高度时处理朝上的射线,再处理水平的射线。朝上的射线用来标记交点横坐标(树状数组单点更新),水平的射线用来统计答案(树状数组区间求和)。

注意:

(1)方向朝下的射线需要特殊处理,转成两条朝上的射线。可能有大量的朝下的射线,所以存射线的数组需开到2*maxn,否则会T(?)。

(2)当射线朝左时,1,x 都是需要考虑的横坐标; 当射线朝右时,x,n-1也都是需要考虑的横坐标;离散化的时候去重就可以。可能有大量的水平方向的射线,所以存横坐标的数组应该开到2*maxn。

ac代码:


#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define lowbit(x) ((x)&(-x))
const int maxn = 2e5+10;
struct node{int hor, l, r, height, val;//hor为1表示水平friend bool operator < (node a, node b){return  a.height == b.height ? a.hor < b.hor : a.height < b.height;//从低到高开始处理,同高度先处理竖直方向的射线}
}Line[maxn];
int n, m, k, numl, numx;
int xx[maxn], c[maxn]={0};void update(int x, int v)
{for(int i = x; i <= numx; i += lowbit(i))c[i] += v;
}
ll getsum(int x)
{ll ans = 0;for(int i = x; i > 0; i -= lowbit(i))ans += c[i];return ans;
}
int get_rank(int x)
{return lower_bound(xx+1, xx+numx+1, x) - xx;
}
ll solve()
{ll ans = 0;sort(Line, Line+numl);sort(xx+1, xx+numx);numx = unique(xx+1, xx+numx) - xx;//去重后的元素个数//cout << "numx: " << numx << endl;numx--;//不同的元素个数for(int i =1; i <= numx; i++) c[i] = 0;for(int i = 0; i < numl; i++){// printf("%d %d %d\n",Line[i].l, Line[i].r, Line[i].height);if(Line[i].hor == 0)//竖直方向,的R无意义update(get_rank(Line[i].l), Line[i].val);elseans += getsum(get_rank(Line[i].r)) - getsum(get_rank(Line[i].l)-1);}return ans + 1;
}
int main()
{//freopen("/Users/zhangkanqi/Desktop/11.txt","r",stdin);int t;scanf("%d", &t);while(t--){int x, y;char ch;numl = 0, numx = 1;scanf("%d %d %d", &n, &m, &k);for(int i = 1; i <= k; i++){scanf("%d %d %c", &x, &y, &ch);if(ch == 'U') Line[numl++] = (node){0, x, -1, y, 1};if(ch == 'D'){Line[numl++] = (node){0, x, -1, 0, 1};Line[numl++] = (node){0, x, -1, y+1, -1};}if(ch == 'L'){xx[numx++] = 1;Line[numl++] = (node){1, 1, x, y, 0};}if(ch == 'R'){xx[numx++] = n-1;Line[numl++] = (node){1, x, n-1, y, 0};}xx[numx++] = x;}printf("%lld\n", solve());}return 0;
}

【2019杭电多校第九场1002=HDU6681】Rikka with Cake(离散化+树状数组+思维)相关推荐

  1. 【2019杭电多校训练赛】HDU6681 / 1002-Rikka with Cake 题解(扫描线)

    [2019杭电多校训练赛]HDU6681 / 1002-Rikka with Cake 题解 题意 思路 代码 题目来自于:HDU6681 Rikka with Cake 题意 题目的大意是给定你一个 ...

  2. 2019杭电多校第九场 Rikka with Cake (hdu6681)

    题意:给出一个n * m的蛋糕,切 k 刀,每次从一个点(x,y)向 上下左右的一个方向切,问最后蛋糕被切成了几块 题解:显然,蛋糕的块数就是那么多线段的交点数 + 1.先离散,考虑向左切和向上切的, ...

  3. 2018 Multi-University Training Contest 9 杭电多校第九场 (有坑待补)

    咕咕咕了太久  多校博客直接从第三场跳到了第九场orz 见谅见谅(会补的!) 明明最后看下来是dp场 但是硬生生被我们做成了组合数专场-- 听说jls把我们用组合数做的题都用dp来了遍 这里只放了用组 ...

  4. 2019杭电多校第一场 Operation HDU - 6579

    题意:给出一个序列,两种操作,求区间[l,r]的区间最大异或和,和在末尾添加一个数 思路:强制在线,保存每个线性基的数值,接下去直接去搜第r个线性基,但要保持时间比l要大,新增了一个pos数组代表一个 ...

  5. 2019杭电多校第一场 HDU 6599

    题解 枚举所有的回文串 注意,本质不同的回文串最多只有∣S∣|S|∣S∣个 在这些回文串中,有一些是满足要求的,我们对这些串打上标记 首先跑一个ManacherManacherManacher,然后枚 ...

  6. 2019杭电多校第二场1009 HDU6599:求本质不同的回文串长度及数量

    hdu6599:求本质不同的回文串长度及数量 hdu6599题意: manacher+后缀自动机+倍增 $O(nlog(n))$ manacher+后缀数组+二分 $O(nlog(n))$ 回文树(回 ...

  7. 2019杭电多校第9场1002 Rikka with Cake HDU6681

    2019杭电多校第9场1002 Rikka with Cake HDU6681 题意:给你若干个点按上下左右切割平面,最后问平面内有几块被切割开来. 解法1:红黑树+思维+贪心 A:根据欧拉定理可以得 ...

  8. 2019年杭电多校第一场 1001题blank(DP)HDU6578

    2019年杭电多校第一场 1001题blank(DP)HDU6578 解决思路,开一个DP数组来存储0 1 2 3四个字符最后出现的位置,并且在DP中已经==排好序==. DP开四维,DP[i][j] ...

  9. 2019杭电多校 第七场 Kejin Player 6656(求期望值)

    2019杭电多校 第七场 Kejin Player 6656(求期望值) 题目 http://acm.hdu.edu.cn/showproblem.php?pid=6656 题意 给你n,q.表示有n ...

  10. 2019牛客多校第九场AThe power of Fibonacci(广义BM)

    2019牛客多校第九场AThe power of Fibonacci(广义BM) 题目大意 求斐波那契数列m次方的前n项和 解题思路 显然,斐波那契的m次方前缀和依然是线性递推,因此考虑用exBM求解 ...

最新文章

  1. OMG!Semaphore里面居然有这么一个大坑!
  2. 修改路由表来使路由分流
  3. php104.tmp,ThinkPHP5.0多个文件上传后找不到临时文件的修改方法
  4. ClassLoader.getSystemResourceAsStream()
  5. AOP统一处理请求日志
  6. 【快乐水题】509. 斐波那契数
  7. VS2010/MFC编程入门之五十三(Ribbon界面开发:为Ribbon Bar添加控件)
  8. 4邻接、8邻接、m邻接
  9. JAVA入门级教学之(内存中的空指针异常)
  10. k8s 集群居然可以图形化安装了?
  11. oracle存储过程拆分字符串函数,Oracle中利用存储过程来分割字符串
  12. python 批量爬取网页pdf_批量抓取网页pdf文件
  13. Java设计模式 -- GOF23
  14. 普罗米修斯清除历史数据
  15. 安卓移动办公软件_尚朋高科TeeTek云端移动办公系统,云端软件5G时代的趋势
  16. 前端自适应图片留白解决
  17. 无套路!最新官宣的1000+微信红包封面,领取入口戳→
  18. [线段树 标记永久化 单调队列] BZOJ 1171 大sz的游戏 BZOJ 2892 强袭作战
  19. Obama Praises Japanese Partnership
  20. 什么是网络流量劫持?揭秘详解黑客劫持的攻击手段与防御方法

热门文章

  1. Google提供的超强圆角效果
  2. android studio文件读写,Android 中的文件读写操作
  3. php获取微信生成签名的时间戳,微信开发中access_token,js_ticket,时间戳,签名工具
  4. Java、Python网页项目,纯前端项目,无后端参考代码,谨慎下载,全网可视性超强Web项目,免费源码,Js、Html、Css组合网页,可衔接数据库,数据可自行修改,可使用SSM、SpringBoo
  5. Android N-ify使用教程,Xposed新模块 无需升级也能使用Android N新功能
  6. python 特别慢_Python很慢?不一定哦
  7. 生产级mysql双写_生产级Mysql物理全量备份-Xtrabackup
  8. android 判断主线程_腾讯Android面试:Handler中有Loop死循环,为什么没有阻塞主线程...
  9. bom本地储存(附实例)
  10. 函数的基本知识点总结(附实例)