160 lines
4.6 KiB
Java
160 lines
4.6 KiB
Java
|
|
enum Color {
|
|
Red,
|
|
Black
|
|
}
|
|
|
|
|
|
interface FoldFun {
|
|
int Apply(int k, boolean v, int acc);
|
|
}
|
|
|
|
class Tree {
|
|
Color color;
|
|
Tree left;
|
|
int key;
|
|
boolean val;
|
|
Tree right;
|
|
|
|
Tree( Color c, Tree l, int k, boolean v, Tree r) {
|
|
color = c;
|
|
left = l;
|
|
key = k;
|
|
val = v;
|
|
right = r;
|
|
}
|
|
|
|
static Tree Node( Color c, Tree l, int k, boolean v, Tree r) {
|
|
return new Tree(c,l,k,v,r);
|
|
}
|
|
|
|
static boolean isRed( Tree t ) {
|
|
return (t != null && t.color == Color.Red);
|
|
}
|
|
|
|
static Tree balanceRight( int kv, boolean vv, Tree t, Tree n ) {
|
|
if (n == null) {
|
|
return null;
|
|
}
|
|
else if (n.left != null && n.left.color == Color.Red) {
|
|
//case let .Node(_, .Node(.Red, l, kx, vx, r1), ky, vy, r2):
|
|
// return .Node(.Red, .Node(.Black, l, kx, vx, r1), ky, vy, .Node(.Black, r2, kv, vv, t))
|
|
Tree l = n.left;
|
|
return Node( Color.Red, Node( Color.Black, l.left, l.key, l.val, l.right), n.key, n.val, Node(Color.Black, n.right, kv, vv, t));
|
|
}
|
|
else if (n.right != null && n.right.color == Color.Red) {
|
|
//case let .Node(_, l1, ky, vy, .Node(.Red, l2, kx, vx, r)):
|
|
// return .Node(.Red, .Node(.Black, l1, ky, vy, l2), kx, vx, .Node(.Black, r, kv, vv, t))
|
|
Tree r = n.right;
|
|
return Node( Color.Red, Node( Color.Black, n.left, n.key, n.val, r.left), r.key, r.val, Node(Color.Black, r.right, kv, vv, t));
|
|
}
|
|
else {
|
|
//case let .Node(_, l, ky, vy, r):
|
|
// return .Node(.Black, .Node(.Red, l, ky, vy, r), kv, vv, t)
|
|
return Node(Color.Black, Node(Color.Red, n.left, n.key, n.val, n.right), kv, vv, t);
|
|
}
|
|
}
|
|
|
|
static Tree balanceLeft( Tree t, int kv, boolean vv, Tree n ) {
|
|
if (n == null) {
|
|
return null;
|
|
}
|
|
else if (n.left != null && n.left.color == Color.Red) {
|
|
//case let .Node(_, .Node(.Red, l, kx1, vx1, r1), ky, vy, r2):
|
|
// return .Node(.Red, .Node(.Black, t, kv, vv, l), kx1, vx1, .Node(.Black, r1, ky, vy, r2))
|
|
Tree l = n.left;
|
|
return Node( Color.Red, Node( Color.Black, t, kv, vv, l.left), l.key, l.val, Node(Color.Black, l.right, n.key, n.val, n.right));
|
|
}
|
|
else if (n.right != null && n.right.color == Color.Red) {
|
|
//case let .Node(_, l1, ky, vy, .Node(.Red, l2, kx2, vx2, r2)):
|
|
// return .Node(.Red, .Node(.Black, t, kv, vv, l1), ky, vy, .Node(.Black, l2, kx2, vx2, r2))
|
|
Tree r = n.right;
|
|
return Node( Color.Red, Node( Color.Black, t, kv, vv, n.left), n.key, n.val, Node(Color.Black, r.left, r.key, r.val, r.right));
|
|
}
|
|
else {
|
|
//case let .Node (_, l, ky, vy, r):
|
|
// return .Node(.Black, t, kv, vv, .Node(.Red, l, ky, vy, r))
|
|
return Node(Color.Black, t, kv, vv, Node(Color.Red, n.left, n.key, n.val, n.right));
|
|
}
|
|
}
|
|
|
|
static Tree ins(Tree t, int kx, boolean vx ) {
|
|
if (t==null) {
|
|
return Node(Color.Red, null, kx, vx, null);
|
|
}
|
|
else if (t.color == Color.Red) {
|
|
//case let .Node(.Red, a, ky, vy, b):
|
|
if (kx < t.key) {
|
|
return Node(Color.Red, ins(t.left, kx, vx), t.key, t.val, t.right);
|
|
} else if (t.key == kx) {
|
|
return Node(Color.Red, t.left, kx, vx, t.right);
|
|
} else {
|
|
return Node(Color.Red, t.left, t.key, t.val, ins(t.right, kx, vx));
|
|
}
|
|
}
|
|
else { // t.color == Black
|
|
if (kx < t.key) {
|
|
if (isRed(t.left)) {
|
|
return balanceRight(t.key, t.val, t.right, ins(t.left, kx, vx));
|
|
} else {
|
|
return Node(Color.Black, ins(t.left, kx, vx), t.key, t.val, t.right);
|
|
}
|
|
} else if (kx == t.key) {
|
|
return Node(Color.Black, t.left, kx, vx, t.right);
|
|
} else {
|
|
if (isRed(t.right)) {
|
|
return balanceLeft(t.left, t.key, t.val, ins(t.right, kx, vx));
|
|
} else {
|
|
return Node(Color.Black, t.left, t.key, t.val, ins(t.right, kx, vx));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
static Tree setBlack( Tree t ) {
|
|
if (t == null) return t;
|
|
return Node(Color.Black, t.left, t.key, t.val, t.right);
|
|
}
|
|
|
|
static Tree insert (Tree t, int k, boolean v) {
|
|
if (isRed(t)) {
|
|
return setBlack(ins(t, k, v));
|
|
} else {
|
|
return ins(t, k, v);
|
|
}
|
|
}
|
|
|
|
static int Fold( FoldFun f, Tree t, int acc ) {
|
|
while(t != null) {
|
|
acc = Fold(f,t.left,acc);
|
|
acc = f.Apply(t.key,t.val,acc);
|
|
t = t.right;
|
|
}
|
|
return acc;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
public class rbtree
|
|
{
|
|
static Tree mkMap( int n ) {
|
|
Tree t = null;
|
|
while(n > 0) {
|
|
n--;
|
|
t = Tree.insert(t, n, (n%10)==0);
|
|
}
|
|
return t;
|
|
}
|
|
|
|
static int Test(int n ) {
|
|
Tree t = mkMap(n);
|
|
return Tree.Fold( (k,v,acc) -> { return (v ? acc + 1 : acc); }, t, 0);
|
|
}
|
|
|
|
public static void main(String args[])
|
|
{
|
|
System.out.println( Test(Integer.parseInt(args[0])) );
|
|
}
|
|
}
|