-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathSegmentTree.java
162 lines (141 loc) · 3.71 KB
/
SegmentTree.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
import java.util.Arrays;
abstract class SegmentTree < T , V >
{
private T tree[];
private V arr[];
public final int HEIGHT;
public final int SIZE;
public final int ELEMENT;
@SuppressWarnings("unchecked")
SegmentTree(V arr[])
{
ELEMENT=arr.length;
this.arr=Arrays.copyOf(arr, ELEMENT);
HEIGHT=(int)(Math.ceil(Math.log(ELEMENT)/Math.log(2)));
SIZE=2*(int)Math.pow(2, HEIGHT)-1;
tree=(T[])new Object[SIZE];
buildSegmentTree(0,ELEMENT-1,0);
}
public V getValue(int index)
{
return arr[index];
}
private void update(int index,int start,int end,int queryStart,int queryEnd)
{
int overlapValue=overLap(start, end, queryStart, queryEnd);
int mid=getMid(start, end);
switch(overlapValue)
{
case 0:
break;
case 1:
tree[index]=leaf(start);
break;
case 2:
case 3:
case 4:
update(getLeftIndex(index), start, mid, queryStart, queryEnd);
update(getRightIndex(index), mid+1,end, queryStart, queryEnd);
tree[index]= process(tree[getLeftIndex(index)],tree[getRightIndex(index)]);
break;
}
}
//0 based indexing, both inclusive in array arr
public void update(int queryStart,int queryEnd,V x)
{
for(int index=queryStart;index<=queryEnd;index++)
arr[index]=updateAtLeaf(index,x);
update(0,0,ELEMENT-1,queryStart,queryEnd);
}
/*
* changes made at array arr on index with value x, either overwrite or make some delta change e.t.c
*/
public abstract V updateAtLeaf(int index, V x);
private int getLeftIndex(int index)
{
return index*2+1;
}
private int getRightIndex(int index)
{
return index*2+2;
}
//point update at index of arr which is 0th based, value is overwritten on index of arr;
public void update(int index,V value)
{
arr[index]=value;
update(0, 0,ELEMENT-1, index, index);
}
private void buildSegmentTree(int start, int end, int index)
{
if(start>end||index>=SIZE)
return;
else if(start==end)
{
tree[index]=leaf(start);
}
else
{
int mid=getMid(start, end);
buildSegmentTree( start, mid, getLeftIndex(index));
buildSegmentTree( mid+1, end, getRightIndex(index));
tree[index]=process(tree[getLeftIndex(index)],tree[getRightIndex(index)]);
}
}
/*
* value at leaf of segment tree while building
* index is 0th based based on arr
*/
public abstract T leaf(int index) ;
private int overLap(int start,int end,int queryStart,int queryEnd)
{
int mid=getMid(start,end);
if(end<queryStart ||start>end)//no overlap
return 0;
else if(queryStart<=start && end<=queryEnd )//full overlap
return 1;
//partial overlap and types
else if(mid>=queryEnd)//complete left overlap
return 2;
else if(mid < queryStart)//complete right overlap
return 3;
else
return 4;//mix overlap
}
private T getResult(int index,int start,int end,int queryStart,int queryEnd)
{
int overlapValue=overLap(start, end, queryStart, queryEnd);
int mid=getMid(start,end);
switch(overlapValue)
{
case 1:
return tree[index];
case 2:
return getResult(getLeftIndex(index), start, mid, queryStart, queryEnd);
case 3:
return getResult(getRightIndex(index), mid+1,end, queryStart, queryEnd);
case 4:
T left=getResult(getLeftIndex(index), start, mid, queryStart, queryEnd);
T right=getResult(getRightIndex(index), mid+1,end, queryStart, queryEnd);
return process(left,right);
}
return null;
}
private int getMid(int start, int end)
{
// TODO Auto-generated method stub
return (start+end)/2;
}
public T getResult(int queryStart,int queryEnd)
{
return getResult(0, 0, ELEMENT-1, queryStart, queryEnd);
}
/* define this method
* as the relation between two child of the root node
*/
public abstract T process(T left, T right);
@Override
public String toString()
{
return Arrays.toString(tree);
}
}