题意:

给定一块n*m的矩形区域,在区域内有若干点,每个顶点发出一条射线,有上下左右四个方向,问矩形被分成了几个区域?

思路:

稍加观察和枚举可以发现,区域数量=射线交点数+1(可以用欧拉定理验证,但是我不会),问题就转变为统计射线交点数量

可以将四个方向的射线分开,用左右的射线去查询与多少个上下的射线相交,先考虑向左的射线A与几条向上的射线相交,设A(x,y),即求(1,x)区间内\(\le y\)的向上的射线条数,显然可以利用主席树进行维护(也可以用树状数组并且更快,但是我不会)。其他情况同理,注意离散化时向上靠近还是向下靠近

由于y是在(1,1e9)范围内的,因此y需要离散化,因为主席树的性质,x必须排序离散化

//memory= 1.3e8 int
#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <algorithm>
using namespace std;
const int maxn=1e5+5;
const int N=1e5+2;
int xu[maxn],xd[maxn],val[maxn];
int x1[maxn],y1[maxn];
char c1[maxn];
const int Log=50;
int root[2][maxn],num[2][maxn*Log],lson[2][maxn*Log],rson[2][maxn*Log];
int tot[2];
double Sum,Num;
int build(int id,int l,int r){
int root=++tot[id];
num[id][root]=0;
if(l<r){
int mid=(l+r)>>1;
lson[id][root]=build(id,l,mid);
rson[id][root]=build(id,mid+1,r);
}
return root;
}
int update(int id,int pre,int l,int r,int x){
int root=++tot[id];
num[id][root]=num[id][pre]+1;
lson[id][root]=lson[id][pre];
rson[id][root]=rson[id][pre];
if(l<r){
int mid=(l+r)>>1;
if(x<=mid) lson[id][root]=update(id,lson[id][pre],l,mid,x);
else rson[id][root]=update(id,rson[id][pre],mid+1,r,x);
}
return root;
}
int query(int id,int Old,int New,int l,int r,int k){//Old和New对应旧版本的根和新版本的根
if(id==0){//向上,查区间内<=k的数的个数
if(r<=k){
return num[id][New]-num[id][Old];
}
int mid=(l+r)>>1;
int res=0;
if(l<=k) res+=query(id,lson[id][Old],lson[id][New],l,mid,k);
if(mid+1<=k) res+=query(id,rson[id][Old],rson[id][New],mid+1,r,k);
return res;
}
else{//向下,查区间内>=k的数的个数
if(l>=k){
return num[id][New]-num[id][Old];
}
int mid=(l+r)>>1;
int res=0;
if(mid>=k) res+=query(id,lson[id][Old],lson[id][New],l,mid,k);
if(r>=k) res+=query(id,rson[id][Old],rson[id][New],mid+1,r,k);
return res;
}
}
struct node{
node(int a,int b):x(a),y(b){}
int x,y;
};
bool cmp(node a,node b){
return a.x<b.x;
}
int main(){
int t;
cin>>t;
while(t--){
tot[0]=tot[1]=0;
int n,m,k;
vector<node> U,D,R,L;
scanf("%d%d%d",&n,&m,&k);
int x,y;
char c;
int sizexu=0,sizexd=0,sizey=0;
for(int i=1;i<=k;i++){
scanf("%d%d %c",&x,&y,&c);
x1[i]=x;y1[i]=y;c1[i]=c;
if(c=='U') xu[++sizexu]=x;
if(c=='D') xd[++sizexd]=x;
val[++sizey]=y;
}
sort(xu+1,xu+1+sizexu);
sort(xd+1,xd+1+sizexd);
sort(val+1,val+1+sizey);
sizexu=unique(xu+1,xu+1+sizexu)-(xu+1);
sizexd=unique(xd+1,xd+1+sizexd)-(xd+1);
sizey=unique(val+1,val+1+sizey)-(val+1);
for(int i=1;i<=k;i++){//U,D中存离散化的坐标值。L,R存原值,之后再在对应数组中二分找离散值
if(c1[i]=='U'){
x1[i]=lower_bound(xu+1,xu+1+sizexu,x1[i])-xu;
y1[i]=lower_bound(val+1,val+1+sizey,y1[i])-val;
U.push_back(node(x1[i],y1[i]) );
}
if(c1[i]=='D'){
x1[i]=lower_bound(xd+1,xd+1+sizexd,x1[i])-xd;
y1[i]=lower_bound(val+1,val+1+sizey,y1[i])-val;
D.push_back(node(x1[i],y1[i]) );
}
if(c1[i]=='L') L.push_back(node(x1[i],y1[i]) );
if(c1[i]=='R') R.push_back(node(x1[i],y1[i]) );
}
//建2棵主席树,分别存U,D,再用L和R取查找
root[0][0]=build(0,1,N);
root[1][0]=build(1,1,N);
sort(U.begin(),U.end(),cmp);
for(int i=0;i<U.size();i++)
root[0][i+1]=update(0,root[0][i],1,N,U[i].y);
sort(D.begin(),D.end(),cmp);
for(int i=0;i<D.size();i++)
root[1][i+1]=update(1,root[1][i],1,N,D[i].y);
int ans=0;
for(int i=0;i<L.size();i++){
int r0=upper_bound(xu+1,xu+1+sizexu,L[i].x)-xu-1;//找<=,向左靠近
int r1=upper_bound(xd+1,xd+1+sizexd,L[i].x)-xd-1;//找<=,向左靠近
int h=lower_bound(val+1,val+1+sizey,L[i].y)-val;
ans+=query(0,root[0][0],root[0][r0],1,N,h);
ans+=query(1,root[1][0],root[1][r1],1,N,h);
}
for(int i=0;i<R.size();i++){
int l0=lower_bound(xu+1,xu+1+sizexu,R[i].x)-xu;//找>=,向右靠近
int l1=lower_bound(xd+1,xd+1+sizexd,R[i].x)-xd;//找>=,向右靠近
int h=lower_bound(val+1,val+1+sizey,R[i].y)-val;
ans+=query(0,root[0][l0-1],root[0][U.size()],1,N,h);
ans+=query(1,root[1][l1-1],root[1][D.size()],1,N,h);
}
printf("%d\n",ans+1);
}
}

2019杭电多校第⑨场B Rikka with Cake (主席树,离散化)的更多相关文章

  1. 2019杭电多校第一场hdu6581 Vacation

    Vacation 题目传送门 update(O(n)) 看了那个O(n)的方法,感觉自己想的那个O(nlogn)的好傻,awsl. 0车最终通过停车线的时候,状态一定是某个车堵住后面的所有车(这个车也 ...

  2. 2019杭电多校第二场hdu6601 Keen On Everything But Triangle

    Keen On Everything But Triangle 题目传送门 解题思路 利用主席树求区间第k小,先求区间内最大的值,再求第二大,第三大--直到找到连续的三个数可以构成一个三角形.因为对于 ...

  3. 2019杭电多校第二场hdu6602 Longest Subarray(线段树)

    Longest Subarray 题目传送门 解题思路 本题求一个最大的子区间,满足区间内的数字要么出现次数大于等于k次,要么没出现过.给定区间内的数字范围是1~c. 如果r为右边界,对于一种数字x, ...

  4. Rikka with Game[技巧]----2019 杭电多校第九场:1005

      Rikka with Game Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 524288/524288 K (Java/Othe ...

  5. [2019杭电多校第一场][hdu6582]Path(最短路&&最小割)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6582 题意:删掉边使得1到n的最短路改变,删掉边的代价为该边的边权.求最小代价. 比赛时一片浆糊,赛后 ...

  6. [2019杭电多校第二场][hdu6602]Longest Subarray(线段树)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6602 题目大意为求最长的区间,满足C种数字在区间内要么不出现,要么出现的次数都不小于K. 大致的分析一 ...

  7. [2019杭电多校第二场][hdu6601]Keen On Everything But Triangle

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6601 题意是说用给定区间内的数字组成周长最大的三角形. 大致做法就是求区间第1大,第2大和第3大然后判 ...

  8. [2019杭电多校第二场][hdu6599]I Love Palindrome String(回文自动机&&hash)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6599 题目大意为求字符串S有多少个子串S[l,r]满足回文串的定义,并且S[l,(l+r)/2]也满足 ...

  9. [2019杭电多校第二场][hdu6598]Harmonious Army(最小割)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6598 题意是说一个军队有n人,你可以给他们每个人安排战士或者法师的职业,有m对人有组合技,组合技的信息 ...

随机推荐

  1. P4390 [BOI2007]Mokia 摩基亚

    传送门 对于一个询问 $(xa,ya),(xb,yb)$,拆成 $4$ 个询问并容斥一下 具体就是把询问变成求小于等于 $xb,yb$ 的点数,减去小于等于 $xa-1,yb$ 和小于等于 $xb,y ...

  2. java中位运算和移位运算详解

    一.位运算 (1)按 位 与 & 如果两个相应的二进制形式的对应的位数都为1,则结果为1,记为同1为1,否则为0.首先我们看一下对正数的运算        分别看一下正数和负数的具体运算步骤 ...

  3. 在html模板里面加python函数(simple_tag与filter)

    自定义函数 simple_tag a. app下创建templatetags目录 b. 任意xxoo.py文件 c. 创建template对象 register d. @register.simple ...

  4. pycharm修改字体大小和主题

    一,修改文字大小: 二,修改主题:你可能对编辑器的外观仍不满意,例如你希望将文档字符串改变为另外一种颜色,下面介绍具体更改方法:  

  5. 20180329-layoutSubviews的调用机制

    如果你想强制更新布局,不要直接调用此方法,你可以调用setNeedsLayout方法,如果你想立即显示你的views,你需要调用layoutIfNeed方法 layoutSubviews作用: lay ...

  6. 二、Ajax请求MVC中数据查询表返回datatable

    一.Ajax请求MVC中数据查询表返回datatable 解决方式 返回list

  7. 三、SQL Server 对JSON的支持

    一.SQL Server 对JSON的支持 一.实现效果   现在 我用数据库是sql2008 ,共计2万数据. 每一条数据里面的有一个为attribute字段是 json存储状态属性,  我怎么查看 ...

  8. 4.VUE前端框架学习记录四:Vue组件化编码2

    VUE前端框架学习记录四:Vue组件化编码2文字信息没办法描述清楚,主要看编码Demo里面,有附带完整的代码下载地址,有需要的同学到脑图里面自取.脑图地址http://naotu.baidu.com/ ...

  9. 谈一谈测试驱动开发(TDD)的好处以及你的理解

    DD是指在编写真正的功能实现代码之前先写测试代码,然后根据需要重构实现代码.在JUnit的作者Kent Beck的大作<测试驱动开发:实战与模式解析>(Test-Driven Develo ...

  10. spark 计算结果写入mysql 案例及常见问题解决

    package com.jxd import org.apache.spark.SparkContextimport org.apache.spark.SparkConfimport java.sql ...