象限查询
Quadrant Queries
我几乎已经解决了使用延迟传播的段树的 Interviewstreet 的这个象限查询问题,但我仍然得到错误的答案,所以我在我的代码中需要帮助。
这是个问题:
象限查询
平面中有 N 个点。第 i 个点具有坐标 (xi, yi(。执行以下查询:
- 反射点 i 和 j 之间的所有点,包括沿 X 轴的点。此查询表示为
X i j
- 反射点 i 和 j 之间的所有点,包括沿 Y 轴的点。此查询表示为
Y i j
- 计算点 i 和 j 之间的点(包括位于 4 个象限中的每一个(之间的点数。此查询表示为
C i j
输入:
第一行包含 N,即点数。N行紧随其后。
第 i 行包含由空格分隔的 xi 和 yi。
下一行包含 Q 查询数。接下来的 Q 行分别包含一个查询,分别包含上述形式之一的查询。
所有索引均为 1 个索引。
输出:
为类型 C i j
的每个查询输出一行。相应的行包含 4 个整数;指数在 [i..j]分别在第1、2、3和4象限。
约束:
1 <= N <= 100000
1 <= Q <= 100000
You may assume that no point lies on the X or the Y axis.
All (xi,yi) will fit in a 32-bit signed integer
In all queries, 1 <=i <=j <=N
示例输入:
4
1 1
-1 1
-1 -1
1 -1
5
C 1 4
X 2 4
C 3 4
Y 1 2
C 1 3
示例输出:
1 1 1 1
1 1 0 0
0 2 0 1
解释:
当查询显示 X i j
时,这意味着取索引 i 和 j 之间的所有点,包括并反映沿 X 轴的这些点。这里的 i 和 j 与点的坐标无关。它们是指数。I 指点 I,j 指点 J
C 1 4
要求您"考虑索引在 {1,2,3,4} 中的点集。在这些点中,有多少分别位于第一、第二、第三和第四四边形?答案显然是1 1 1 1。
接下来,我们沿 X 轴反映索引 '2 4' 之间的点。所以新的坐标是:
1 1
-1 -1
-1 1
1 1
现在C 3 4
是"考虑在 {3,4} 中具有索引的点集。在这些点中,有多少分别位于第一、第二、第三和第四四边形?点 3 位于象限 2,点 4 位于象限 1。所以答案是 1 1 0 0。
当前代码
这是我在 c 中的解决方案:
void query(int node, int b, int e, int i, int j, char ch)
{
if(L[node][0]!=0 || L[node][1]!=0)
{
if(b!=e){
L[2*node+1][0]=L[node][0];
L[2*node+1][1]=L[node][1];
L[2*node+2][0]=L[node][0];
L[2*node+2][1]=L[node][1];
}
if(L[node][0]%2!=0)
{
tmp=Q[node][0];
Q[node][0]=Q[node][3];
Q[node][3]=tmp;
tmp=Q[node][1];
Q[node][1]=Q[node][2];
Q[node][2]=tmp;
}
if(L[node][1]%2!=0)
{
tmp=Q[node][0];
Q[node][0]=Q[node][1];
Q[node][1]=tmp;
tmp=Q[node][2];
Q[node][2]=Q[node][3];
Q[node][3]=tmp;
}
L[node][0]=0;
L[node][1]=0;
}
if (i > e || j < b)
return ;
if (b >= i && e <= j)
{
if(ch == 'C'){
ans[0]+=Q[node][0];
ans[1]+=Q[node][1];
ans[2]+=Q[node][2];
ans[3]+=Q[node][3];
}
if(ch == 'X')
{
if(b!=e){
L[2*node+1][0]++;
L[2*node+2][0]++;
}
tmp=Q[node][0];
Q[node][0]=Q[node][3];
Q[node][3]=tmp;
tmp=Q[node][1];
Q[node][1]=Q[node][2];
Q[node][2]=tmp;
}
if(ch == 'Y')
{
if(b!=e){
L[2*node+1][1]++;
L[2*node+2][1]++;
}
tmp=Q[node][0];
Q[node][0]=Q[node][1];
Q[node][1]=tmp;
tmp=Q[node][2];
Q[node][2]=Q[node][3];
Q[node][3]=tmp;
}
return ;
}
query(2 * node +1, b, (b + e) / 2, i, j,ch);
query(2 * node + 2, (b + e) / 2 + 1, e, i, j,ch);
Q[node][0]=Q[2*node+1][0] + Q[2*node+2][0];
Q[node][1]=Q[2*node+1][1] + Q[2*node+2][1];
Q[node][2]=Q[2*node+1][2] + Q[2*node+2][2];
Q[node][3]=Q[2*node+1][3] + Q[2*node+2][3];
return ;
}
如果我正确理解了您的算法,那么您正在使用 L 数组来跟踪是否需要翻转一系列点,但将实际翻转推迟到有必要。
在这种情况下,我认为这些行可能存在问题:
void query(int node, int b, int e, int i, int j, char ch)
{
if(L[node][0]!=0 || L[node][1]!=0)
{
if(b!=e){
L[2*node+1][0]=L[node][0];
L[2*node+1][1]=L[node][1];
L[2*node+2][0]=L[node][0];
L[2*node+2][1]=L[node][1];
}
假设 L[node][0] 是 1,而 L[2*node+1][0] 已经是 1。 这意味着前面的某个步骤想要翻转 2*node+1 的节点,然后这一步也想翻转这些节点。 这些翻转应该抵消,L[2*node+1][0] 应该变为零。
我认为您应该将这些行更改为使用异或,以便取消双翻转:
void query(int node, int b, int e, int i, int j, char ch)
{
if(L[node][0]!=0 || L[node][1]!=0)
{
if(b!=e){
L[2*node+1][0]^=L[node][0];
L[2*node+1][1]^=L[node][1];
L[2*node+2][0]^=L[node][0];
L[2*node+2][1]^=L[node][1];
}
(或者也许我误解了这种方法!
- Mongodb c++驱动程序:如何查询元素的数组
- 查询SQLite数据库中的日期
- 如何在ArangoDb AQL查询中指定数据库
- Qt SQLite没有查询或参数计数不匹配
- 如何使用c++在VS 2019上运行SQL查询
- 从返回的顶点缓冲区查询顶点结构
- 以非特权用户身份查询 NTFS 特殊文件的元数据?
- C/C++ - 查询平台相关的换行符(用于内存映射文件)
- 查询 NFS 上的提升进程间::file_lock
- Qt JSON – 从子项查询
- 在 c++ 中解决段树以外的范围查询的有效方法是什么?
- 无法从 Win10 中的 IDirectDraw7 查询 IDirect3D7
- 如何查询以确定我的 MacOS/X 应用程序是否处于应用程序午睡模式?
- 在子数组中查找多个查询的不同(唯一)值的数量
- DNS 查询格式标头结构中的小字节序问题
- QSql查询行受影响的结果
- C++库相关查询
- 优化使用 C++ 查询 SQLite DB 中超过 5000 万条数据记录的方式
- MongoDB 使用数组中的 OR 条件构建查询
- IAR C 编译器开关:快速查询