2019杭电暑期多校第九场 B:Rikka with Cake(离散化+树状数组)

【题解】

题意:给定平面大小,左下角坐标(0,0),右上角坐标(n,m),给定k条以(xi,yi)为起始点方向为di的射线,询问被切割成多少块。

思路:因为 0<xi<n,0<yi<m,又是射线,所以容易得到最终的块数是所有射线的交点数+1。

因为n和m比较大而点比较少,我们考虑把坐标离散化建立树状数组,用来维护每一条横线的贡献。

整个过程从下往上依次处理查询,所以按y升序排序,且相同的y竖线优先处理。

先把横线和竖线区别处理,用 f 标记是横线还是竖线,

如果是竖线:

如果是向上的竖线,那么从y开始持续有贡献;如果向下,那么从0-y有贡献,所以要再增加一个记录y+1开始没有贡献的点便于后续树状数组的修改操作。

如果是横线:

记录(L,R]表示可到达的部分。

然后轮到竖线就修改树状数组,轮到横线就计算贡献更新答案即可。

代码借鉴于2019杭电暑假多校9:Rikka with Cake【扫描线+树状数组】

【代码】

#include 
using namespace std;
typedef long long LL;
const int maxn=2e5+10;
int n,m,k,cnt,cntx;
struct P{
    int f,L,R,id,v; //f区分横竖线
}p[maxn<<1];
int tr[maxn<<1],X[maxn<<1];
bool cmp(P a,P b){return a.id==b.id?a.f

 

你可能感兴趣的:(2019杭电暑期多校第九场 B:Rikka with Cake(离散化+树状数组))