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

一个线段树的算法题,该如何解决

2013-01-06 
一个线段树的算法题来自interview street的算法题,Quadrant Queries (30 points) There are N points in t

一个线段树的算法题
来自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
需要使用线段树,但是我的实现:

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 number
quadNum = [[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]] += 1

tree = 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上没有调整的话那超时是正常的。

热点排行