首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 软件管理 > 软件架构设计 >

一个线段树的算法题,该如何处理

2012-09-03 
一个线段树的算法题来自interview street的算法题,Quadrant Queries (30 points)There are N points in th

一个线段树的算法题
来自interview street的算法题,
Quadrant Queries (30 points)

 There are N points in the plane. The ith point has coordinates (xi, yi). Perform the following queries: 
 

1) Reflect all points between point i and j both including along the X axis. This query is represented as "X i j"
 2) Reflect all points between point i and j both including along the Y axis. This query is represented as "Y i j"
 3) Count how many points between point i and j both including lie in each of the 4 quadrants. This query is represented as "C i j"

 Input:
 The first line contains N, the number of points. N lines follow. 
 
The ith line contains xi and yi separated by a space. 
 
The next line contains Q the number of queries. The next Q lines contain one query each, of one of the above forms. 
 
All indices are 1 indexed.

 


Output:
 
Output one line for each query of the type "C i j". The corresponding line contains 4 integers; the number of points having indices in the range [i..j] in the 1st,2nd,3rd and 4th quadrants respectively.
 

Constraints:
 1 <= N <= 100000
 1 <= Q <= 1000000
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
 
Sample Input:  
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
 



Sample Output:
 
1 1 1 1
 
1 1 0 0
 
0 2 0 1
 



Explanation
 
 
 
When a query says "X i j", it means that take all the points between indices i and j both including and reflect those points along the X axis. The i and j here have nothing to do with the co-ordinates of the points. They are the indices. i refers to point i and j refers to point j
 
 
 


'C 1 4' asks you to 'Consider the set of points having index in {1,2,3,4}. Amongst those points, how many of them lie in the 1st,2nd,3rd and 4th quads respectively?' 
 

The answer to this is clearly 1 1 1 1.
 
 
 
Next we reflect the points between indices '2 4' along the X axis. So the new coordinates are :
 
1 1
 
-1 -1
 
-1 1
 
1 1
 
 
 
Now 'C 3 4' is 'Consider the set of points having index in {3,4}. Amongst those points, how many of them lie in the 1st,2nd,3rd and 4th quads respectively?' Point 3 lies in quadrant 2 and point 4 lies in quadrant 1. 
 
So the answer is 1 1 0 0
需要使用线段树,但是我的实现:

Python code
class STree:       def __init__(self):        self.i = 0        self.j = 0                self.left = None        self.right = None        self.xFlip = 0  #延迟标记        self.yFlip = 0        self.quadNum = [0]*4        self.parent = None                      def build(self, i, j, quadNum, quad):        #node interval and quadNum        self.i, self.j = i, j        for k in range(4):            self.quadNum[k] = quadNum[j][k] - quadNum[i-1][k]                       if i == j:                                  return        mid = (i+j)//2        self.left  = STree()        self.right = STree()        self.left.parent = self        self.right.parent = self                       self.left.build(i, mid, quadNum, quad)        self.right.build(mid+1, j, quadNum, quad)            #type 0->x. 1->y    def updateQuad(self, type):        curQuadNum = [0]*4        if type == 0:            curQuadNum[0], curQuadNum[1], curQuadNum[2], curQuadNum[3] = \            self.quadNum[3], self.quadNum[2], self.quadNum[1], self.quadNum[0]        else:            curQuadNum[0], curQuadNum[1], curQuadNum[2], curQuadNum[3] = \            self.quadNum[1], self.quadNum[0], self.quadNum[3], self.quadNum[2]                     #print(self.quadNum)                       for k in range(4):            dQuadNum[k] = curQuadNum[k] - self.quadNum[k]        #print('type %d %d %d' %(type, self.i, self.j))        #print(dQuadNum)        #change self and ancestor        if dQuadNum == [0, 0, 0, 0]:            return          parent = self        while parent:            parent.quadNum = [u+v for u, v in zip(dQuadNum, parent.quadNum)]            parent = parent.parent        return        def updateNodeX(self):        self.quadNum[0], self.quadNum[1], self.quadNum[2], self.quadNum[3] = \            self.quadNum[3], self.quadNum[2], self.quadNum[1], self.quadNum[0]                              def updateNodeY(self):        self.quadNum[0], self.quadNum[1], self.quadNum[2], self.quadNum[3] = \            self.quadNum[1], self.quadNum[0], self.quadNum[3], self.quadNum[2]     #将延迟标记向子节点推                     def pushDownLable(self):        if self.xFlip == 1:                self.updateNodeX()                if self.left:   self.left.xFlip = 1 - self.left.xFlip                if self.right:  self.right.xFlip = 1 - self.right.xFlip                                self.xFlip = 0        if self.yFlip == 1:                self.updateNodeY()                if self.left:  self.left.yFlip = 1 - self.left.yFlip                if self.right: self.right.yFlip = 1 - self.right.yFlip                 self.yFlip = 0    #查询    def query(self, i, j):        #push down the label        #update delay        self.pushDownLable()                       if i<=self.i and j>=self.j:            #print('node %d %d %d %d' %(i, j, self.i, self.j))            #print('%d %d %d %d' %(self.quadNum[0], self.quadNum[1], self.quadNum[2], self.quadNum[3]))            return self.quadNum        mid = (self.i+self.j)//2        #contain this node        rst = [0]*4         if self.left and i<= mid:            lrst = self.left.query(i, j)            rst = [u+v for u,v in zip(rst, lrst)]        if self.right and j>=mid+1:            rrst = self.right.query(i, j)            rst = [u+v for u,v in zip(rst, rrst)]        return rst        #翻转线段    def updateFlip(self, i, j, type):        self.pushDownLable()           if i<=self.i and j>=self.j:            #update parent            #print('xflip %d %d %d %d' %(i, j, self.i, self.j))            self.updateQuad(type)            #marker delay to children            if self.left and type == 0:                self.left.xFlip = 1 - self.left.xFlip            if self.right and type == 0:                self.right.xFlip = 1 - self.right.xFlip            if self.left and type == 1:                self.left.yFlip = 1- self.right.yFlip            if self.right and type == 1:                self.right.yFlip = 1 - self.right.yFlip            return        mid = (self.i+self.j)//2               if self.left and i<= mid:            self.left.updateFlip(i, j, type)        if self.right and j>=mid+1:            self.right.updateFlip(i, j, type)N = int(raw_input())quad = [0]*(N+1)for i in range(1, N+1):    t = raw_input().split(' ')    x, y = int(t[0]), int(t[1])    if x > 0 and y > 0:        quad[i] = 0    elif x<0 and y > 0:        quad[i] = 1    elif x<0 and y<0:        quad[i] = 2    else:        quad[i] = 3#cache the numberquadNum = [[0 for i in range(4)] for j in range(N+1)]for i in range(1,N+1):    for j in range(4):        quadNum[i][j] = quadNum[i-1][j]             quadNum[i][quad[i]] += 1tree = STree()tree.build(1, N, quadNum, quad)M = int(raw_input())for i in range(M):    t = raw_input().split(' ')       q, j, k = t[0], int(t[1]), int(t[2])        if q == 'C':        num = tree.query(j, k)        print('%d %d %d %d' %(num[0], num[1], num[2], num[3]))            elif q == 'X':        tree.updateFlip(j, k, 0)          elif q == 'Y':        tree.updateFlip(j, k, 1) 


 给出的是wrong answer,查了很久一直没有查出来。
 请帮忙一下,我怀疑自己在算法上有问题。
 非常感谢。

[解决办法]
蚵蚵。稍微调试了两下就发现问题了。你肯定要哭死
if self.left and type == 0:
self.left.xFlip = 1 - self.left.xFlip
if self.right and type == 0:
self.right.xFlip = 1 - self.right.xFlip
if self.left and type == 1:
self.left.yFlip = 1- self.right.yFlip
if self.right and type == 1:
self.right.yFlip = 1 - self.right.yFlip
---------------------------
self.left.yFlip = 1- self.right.yFlip
[解决办法]
我当年写oj的时候测定下来python要比c慢10~20倍。如果oj上没有调整的话那超时是正常的。

热点排行