我几乎已经使用具有延迟传播的分段树解决了Interviewstreet的象限查询问题,但我仍然得到错误的答案,所以我需要在我的代码中提供帮助。
这就是问题:
象限查询
飞机上有N个点。第i个点具有坐标(xi,yi)。执行以下查询:
X i j
Y i j
C i j
第一行包含N,即点数。 N行跟随。
第i行包含由空格分隔的xi和yi。
下一行包含Q查询的数量。下一个Q行每个包含一个查询,其中一个是上述形式之一。
所有指数均为1个索引。
为类型C i j
的每个查询输出一行。对应的行包含4个整数;分别在第1,第2,第3和第4象限中具有[i..j]范围内的指数的点数。
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,j指的是点j
C 1 4
要求你'考虑{1,2,3,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}中具有索引的点集。在这些点中,有多少分别位于第1,第2,第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 ;
}
答案 0 :(得分:1)
如果我正确理解你的算法,你正在使用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]应该为零。
我认为您应该更改这些行以使用xor,以便双击将取消:
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];
}
(或许我误解了这种方法!)