WEBVTT

00:00:00.090 --> 00:00:02.631
ANNOUNCER: The following content
is provided under a Creative

00:00:02.631 --> 00:00:04.059
Commons license.

00:00:04.059 --> 00:00:06.360
Your support will help
MIT OpenCourseWare

00:00:06.360 --> 00:00:10.720
continue to offer high quality
educational resources for free.

00:00:10.720 --> 00:00:13.320
To make a donation or
view additional materials

00:00:13.320 --> 00:00:17.280
from hundreds of MIT courses,
visit MIT OpenCourseWare

00:00:17.280 --> 00:00:20.485
at ocw@mit.edu

00:00:20.485 --> 00:00:22.860
PROFESSOR: So today we're
going to cover a data structure

00:00:22.860 --> 00:00:24.240
called link-cut trees.

00:00:24.240 --> 00:00:27.300
A cool way of maintaining
dynamic trees,

00:00:27.300 --> 00:00:29.910
and it begins our study
of dynamic graphs.

00:00:29.910 --> 00:00:32.850
Where in general, we have
a graph usually undirected.

00:00:32.850 --> 00:00:35.710
You want to support insertion
and deletion of edges.

00:00:35.710 --> 00:00:38.970
So we're going to do that in
the situation where at all times

00:00:38.970 --> 00:00:40.190
our graphs are trees.

00:00:40.190 --> 00:00:42.420
So in general, we
have a forest of trees

00:00:42.420 --> 00:00:44.440
and we want to maintain them.

00:00:44.440 --> 00:00:49.229
So that will be our only
data structure today

00:00:49.229 --> 00:00:50.520
because it's a bit complicated.

00:00:50.520 --> 00:00:53.370
It's going to need some
fancy amortization.

00:00:53.370 --> 00:00:56.880
And two techniques
for splitting trees

00:00:56.880 --> 00:00:58.650
into paths, one
we've seen already

00:00:58.650 --> 00:01:00.570
in the context of tango
trees and lecture's

00:01:00.570 --> 00:01:02.514
six, preferred paths.

00:01:02.514 --> 00:01:03.930
And another, which
we haven't seen

00:01:03.930 --> 00:01:07.200
is probably my favorite
technique in data structures,

00:01:07.200 --> 00:01:09.847
actually, heavy
like decomposition.

00:01:09.847 --> 00:01:12.180
The technique and data structure
that I've used the most

00:01:12.180 --> 00:01:14.120
outside of data structures.

00:01:14.120 --> 00:01:16.111
It's very useful in
lots of settings.

00:01:16.111 --> 00:01:17.610
Whenever you have
an unbalanced tree

00:01:17.610 --> 00:01:22.720
and you want to make it balance,
like with like cut trees,

00:01:22.720 --> 00:01:25.030
It's the go to tool.

00:01:25.030 --> 00:01:29.955
So, in, general we want to
maintain a forest of trees.

00:01:37.740 --> 00:01:41.515
And these are going to be
rooted unordered trees.

00:01:45.270 --> 00:01:47.650
So arbitrary degree I this.

00:01:50.700 --> 00:01:53.070
And we have a bunch of
operations we want to do.

00:01:53.070 --> 00:01:55.650
Basically, insertion and
deletion of edges and some

00:01:55.650 --> 00:01:57.060
queries.

00:01:57.060 --> 00:01:59.340
And we want to do all
of those operations

00:01:59.340 --> 00:02:00.990
in the log n time per operation.

00:02:04.980 --> 00:02:06.780
That's the hard part.

00:02:06.780 --> 00:02:12.360
So we have some kind of getting
started operation make tree.

00:02:12.360 --> 00:02:17.430
This is going to be make a new
vertex in a new tree, return.

00:02:17.430 --> 00:02:18.040
It.

00:02:18.040 --> 00:02:20.700
So this is how you add
notes to the structure.

00:02:20.700 --> 00:02:23.160
And we're not going to
worry about doing deletions.

00:02:23.160 --> 00:02:26.744
Once you add something
it stays there forever.

00:02:26.744 --> 00:02:28.035
So you could you could do that.

00:02:28.035 --> 00:02:29.570
It's no big deal.

00:02:29.570 --> 00:02:31.650
You could throw away a tree.

00:02:31.650 --> 00:02:33.350
Then we have link
which is essentially

00:02:33.350 --> 00:02:35.790
the insertion of an edge.

00:02:35.790 --> 00:02:39.030
So here we're given
two vertices BMW

00:02:39.030 --> 00:02:42.540
that are in different
trees as a precondition.

00:02:42.540 --> 00:02:46.590
So v has to be at
the root of its tree.

00:02:46.590 --> 00:02:48.870
W can be any node.

00:02:48.870 --> 00:02:53.580
So here we have another tree
and we have some node w inside v

00:02:53.580 --> 00:02:59.760
And the link operation
adds V as a child of W.

00:02:59.760 --> 00:03:03.530
So we add this edge.

00:03:03.530 --> 00:03:06.889
OK, that, of course, combines
two trees into one tree.

00:03:06.889 --> 00:03:09.180
And the requirement is BMW
has to be in different trees

00:03:09.180 --> 00:03:10.888
or otherwise you'd be
adding a cycle that

00:03:10.888 --> 00:03:15.710
doesn't satisfy that were
always a forest of trees.

00:03:15.710 --> 00:03:23.340
Then we have a cut operation,
which is basically the reverse.

00:03:23.340 --> 00:03:25.260
So let me draw it.

00:03:25.260 --> 00:03:30.090
We have V subtree parent.

00:03:30.090 --> 00:03:33.120
And there is a
whole tree up here.

00:03:36.130 --> 00:03:40.350
And what we want to do
is remove that edge.

00:03:40.350 --> 00:03:43.590
So that splits one tree into
two trees by the leading

00:03:43.590 --> 00:03:44.970
edge from V to its parent.

00:03:54.800 --> 00:03:57.570
OK so those are our updates.

00:03:57.570 --> 00:04:01.830
Pretty obvious in the
setting of dynamic graphs.

00:04:01.830 --> 00:04:04.690
Of course, it's the
first time we see them.

00:04:04.690 --> 00:04:05.812
Now we have some queries.

00:04:05.812 --> 00:04:07.270
There are lots of
different queries

00:04:07.270 --> 00:04:09.940
that cut-trees can support.

00:04:09.940 --> 00:04:18.430
One of the most basic is
find the root of vertex.

00:04:18.430 --> 00:04:19.750
Let me just draw a picture of.

00:04:19.750 --> 00:04:24.460
It you have some
vertex V, you want

00:04:24.460 --> 00:04:27.360
to return the root of the tree.

00:04:27.360 --> 00:04:34.160
So find R. And that's
pretty easy to do.

00:04:34.160 --> 00:04:38.570
Well actually see it in
next class, next lecture,

00:04:38.570 --> 00:04:40.940
if you wanted to make
tree/link cut and find root,

00:04:40.940 --> 00:04:44.450
there's a really easy way to
do them in logarithmic time.

00:04:44.450 --> 00:04:47.090
link-cut trees is a harder
way to do it in log n time,

00:04:47.090 --> 00:04:49.710
but they support a lot
of other operations.

00:04:49.710 --> 00:04:59.020
And in particular, something
called path aggregation.

00:04:59.020 --> 00:05:04.420
This is kind of the essence
of link/cut are cool.

00:05:04.420 --> 00:05:07.790
Let's suppose you
have a for a tree,

00:05:07.790 --> 00:05:13.210
you have a vertex V.
There's a root to V path.

00:05:13.210 --> 00:05:15.850
And let's suppose that every
node or every edge, doesn't

00:05:15.850 --> 00:05:17.530
matter, has a weight on it.

00:05:17.530 --> 00:05:19.700
Just some real number.

00:05:19.700 --> 00:05:22.150
Then path aggregation
can do things

00:05:22.150 --> 00:05:27.850
like the min or
the max or the sum

00:05:27.850 --> 00:05:31.705
or the product or whatever
of weights on that path.

00:05:41.102 --> 00:05:42.310
And this is a powerful thing.

00:05:42.310 --> 00:05:44.768
And it's actually the reason
link/cut trees were originally

00:05:44.768 --> 00:05:47.110
invented for doing network
flow algorithms faster.

00:05:47.110 --> 00:05:49.519
If you know network
flow algorithms.

00:05:49.519 --> 00:05:51.560
Or maybe you've seen them
in advanced algorithms.

00:05:51.560 --> 00:05:53.440
This is sort of the key
thing you need to do.

00:05:53.440 --> 00:05:58.270
You find, I think, min way
edge along one of these paths

00:05:58.270 --> 00:06:01.170
and that's the max you can push
in a push reliable strategy.

00:06:01.170 --> 00:06:03.670
I don't want to get into that
because that's algorithms, not

00:06:03.670 --> 00:06:05.000
data structures.

00:06:05.000 --> 00:06:06.670
But this is why
they were invented.

00:06:06.670 --> 00:06:11.230
And, in general, link/cut
trees have a very strong kind

00:06:11.230 --> 00:06:12.652
of path thing.

00:06:12.652 --> 00:06:14.360
If you want to know
anything about a root

00:06:14.360 --> 00:06:18.100
to the path for any
node v, link-cut trees

00:06:18.100 --> 00:06:20.030
can do whatever you
want in lon n time.

00:06:20.030 --> 00:06:22.310
This is just sort of
an example of that.

00:06:22.310 --> 00:06:24.750
And Yeah.

00:06:24.750 --> 00:06:25.290
course.

00:06:25.290 --> 00:06:27.370
So that's what link
countries are able to do.

00:06:27.370 --> 00:06:31.060
All these operations in log
n And the main point here

00:06:31.060 --> 00:06:34.540
is that the trees are storing
are probably not balanced.

00:06:34.540 --> 00:06:38.120
It could be a path,
could be depth

00:06:38.120 --> 00:06:41.770
and is this path we're talking
about could be length order

00:06:41.770 --> 00:06:44.320
n is really bad.

00:06:44.320 --> 00:06:46.704
And yet, we can do all these
operations in log n time.

00:06:46.704 --> 00:06:48.370
And we're going to
do that, essentially,

00:06:48.370 --> 00:06:52.240
by storing the unbalanced
tree that you're

00:06:52.240 --> 00:06:57.010
trying to represent, which we
call this the represent tree.

00:06:57.010 --> 00:07:00.430
We're going to store it using,
essentially, a balanced tree.

00:07:00.430 --> 00:07:01.870
In one version of
link-cut trees,

00:07:01.870 --> 00:07:06.180
indeed, we store all the
nodes in a log n height tree.

00:07:06.180 --> 00:07:08.380
The version we're
going to cover here--

00:07:08.380 --> 00:07:10.600
there's several versions
of link-cut trees.

00:07:10.600 --> 00:07:15.580
Original are biased
later in Tarjan in 1983.

00:07:15.580 --> 00:07:18.520
And then Tarjan wrote a
book, one of a few books

00:07:18.520 --> 00:07:19.750
on data structures.

00:07:19.750 --> 00:07:23.980
Very thin book, usually called
Tarjan's little book, in 1984.

00:07:23.980 --> 00:07:26.160
And it has a different
version of link-cut trees,

00:07:26.160 --> 00:07:27.576
and that's the
version we're going

00:07:27.576 --> 00:07:29.609
to cover it uses splay
trees as a subroutine.

00:07:29.609 --> 00:07:31.400
So it's not going to
be perfectly balanced.

00:07:31.400 --> 00:07:33.930
It's going to be balanced
in an amortize sense,

00:07:33.930 --> 00:07:38.320
or vaguely balanced,
roughly balanced, whatever.

00:07:38.320 --> 00:07:41.530
But there is a version that does
everything in log n worse case

00:07:41.530 --> 00:07:42.130
pre-operation.

00:07:42.130 --> 00:07:45.850
If there's time, I'll sketch
that for you at the end.

00:07:45.850 --> 00:07:50.260
But the simplest version I know
is this splay tree version.

00:07:50.260 --> 00:07:55.120
And it's also kind of fun
because the version we'll see,

00:07:55.120 --> 00:07:56.950
doesn't really look
like it should work,

00:07:56.950 --> 00:08:01.550
and yet it does thanks to
splay trees, essentially.

00:08:01.550 --> 00:08:03.970
So it's a little, it's fun
and surprising in that sense.

00:08:15.610 --> 00:08:20.214
As I said, link-cut trees are
all about paths in the tree.

00:08:20.214 --> 00:08:22.380
And so somehow we want to
split a tree up into paths

00:08:22.380 --> 00:08:24.210
and we've already
seen a way to do this.

00:08:24.210 --> 00:08:26.290
The preferred path
decomposition.

00:08:26.290 --> 00:08:29.970
So it's kind of reminding
you, but I'm also

00:08:29.970 --> 00:08:33.230
going to slightly redefine
it, if I recall correctly.

00:08:33.230 --> 00:08:38.209
It's just a minor
difference which

00:08:38.209 --> 00:08:39.669
I can talk about a second.

00:08:39.669 --> 00:08:42.900
The notion of a preferred
child of a node, and it's

00:08:42.900 --> 00:08:43.875
going to be two cases.

00:08:47.770 --> 00:08:53.960
There isn't a preferred
child, if the last access

00:08:53.960 --> 00:09:04.020
in these subtree is v. So
we have some node v. Now,

00:09:04.020 --> 00:09:07.430
this is relative to
the represented tree.

00:09:07.430 --> 00:09:10.260
So we have some node to v.
We don't care about accesses

00:09:10.260 --> 00:09:13.350
outside of that subtree, but
of the last access within

00:09:13.350 --> 00:09:17.730
the subtree was v itself, then
there's no preferred child.

00:09:17.730 --> 00:09:20.220
Otherwise, the last
access within the tree

00:09:20.220 --> 00:09:22.900
was in one of these
child subtrees.

00:09:22.900 --> 00:09:25.980
And whichever one it was, we
say w is the preferred child.

00:09:29.020 --> 00:09:42.091
So if the last access in
v subtree is in child w's

00:09:42.091 --> 00:09:42.590
subtree.

00:09:45.430 --> 00:09:47.630
OK, I think last time we
defined preferred children

00:09:47.630 --> 00:09:50.930
in the context of tango trees,
we just had the second part.

00:09:50.930 --> 00:09:53.330
So if there is an access
to v, we ignored it

00:09:53.330 --> 00:09:55.460
and we just consider what
the last child access.

00:09:55.460 --> 00:09:57.470
Was I don't think
there's actually

00:09:57.470 --> 00:09:59.120
would affect tango
trees, but I think

00:09:59.120 --> 00:10:00.440
it does effect Link-cut trees.

00:10:00.440 --> 00:10:02.180
So I want to define it this way.

00:10:02.180 --> 00:10:05.390
It'll make life
cleaner, basically.

00:10:05.390 --> 00:10:08.210
Probably not a huge
difference either way.

00:10:08.210 --> 00:10:09.980
OK, once you have
preferred children,

00:10:09.980 --> 00:10:13.250
that gives you one outgoing
edge, downward edge,

00:10:13.250 --> 00:10:14.720
from every node.

00:10:14.720 --> 00:10:21.620
And so we get preferred
paths by repeatedly following

00:10:21.620 --> 00:10:23.090
preferred child pointers.

00:10:23.090 --> 00:10:27.250
Now, we may stop at some
point because we reach a none.

00:10:27.250 --> 00:10:31.610
I'm going to use none as like
null pointers in this lecture.

00:10:31.610 --> 00:10:34.910
But, in general, we have some
tree and you follow for a while

00:10:34.910 --> 00:10:38.450
and then it's going to be a
bunch of things like this.

00:10:38.450 --> 00:10:49.430
We decompose the nodes
and the represented tree,

00:10:49.430 --> 00:10:50.460
partition the nodes.

00:10:54.350 --> 00:10:57.110
Every node belongs to
some preferred path.

00:10:57.110 --> 00:11:00.770
So basic idea is we're
going to store the preferred

00:11:00.770 --> 00:11:05.720
paths in kind of balanced binary
search trees, splay trees,

00:11:05.720 --> 00:11:08.330
and then we're going to connect
them together because that's

00:11:08.330 --> 00:11:10.770
not all the edges in the tree.

00:11:10.770 --> 00:11:15.810
There's some edges that
sort of connect them,

00:11:15.810 --> 00:11:16.970
connect the paths together.

00:11:16.970 --> 00:11:19.670
That's where the
tree part comes in.

00:11:19.670 --> 00:11:22.700
That's what we're going to do
it this thing is unbalanced.

00:11:22.700 --> 00:11:25.190
We're going to take each
of these white lines

00:11:25.190 --> 00:11:28.190
and compress it
into a splay tree,

00:11:28.190 --> 00:11:29.590
and preserve the red pointers.

00:11:33.721 --> 00:11:37.090
I'll write that down.

00:11:37.090 --> 00:11:41.350
These are called
auxiliary trees.

00:11:41.350 --> 00:11:44.760
This was exactly the
idea and tango trace

00:11:44.760 --> 00:11:48.310
and I'm using tango
tree terminology

00:11:48.310 --> 00:11:50.880
to keep it consistent
with that notation.

00:11:50.880 --> 00:11:54.700
It wasn't called preferred paths
in the link-cut tree papers.

00:11:54.700 --> 00:11:58.270
Or it wasn't called auxiliary
trees, but same difference.

00:11:58.270 --> 00:12:06.940
So auxiliary trees were going to
store represent each preferred

00:12:06.940 --> 00:12:16.380
path by a splay tree.

00:12:16.380 --> 00:12:21.079
Tango trees we use
red-black trees or whatever.

00:12:21.079 --> 00:12:22.662
Could us splay trees,
actually, if you

00:12:22.662 --> 00:12:25.540
use tango trees with splay
trees for each preferred path.

00:12:25.540 --> 00:12:27.650
It's called a multi-splay tree.

00:12:27.650 --> 00:12:31.020
Multi-splay trees are almost
identical to link-cut trees

00:12:31.020 --> 00:12:32.770
but, they're used for
a different setting.

00:12:32.770 --> 00:12:37.380
The use for proving
log n competitiveness.

00:12:37.380 --> 00:12:40.210
Here we're doing it to
represent a specific tree.

00:12:40.210 --> 00:12:43.420
With tango trees, the
tree we're representing

00:12:43.420 --> 00:12:45.190
was just a perfect
binary tree, p.

00:12:45.190 --> 00:12:48.179
So you may recall, here
it has some meaning.

00:12:48.179 --> 00:12:49.720
And it's going to
be changing, and we

00:12:49.720 --> 00:12:53.060
care about how it's changing.

00:12:53.060 --> 00:12:57.520
OK, another difference is
we're going to key the nodes

00:12:57.520 --> 00:12:59.290
by depth.

00:12:59.290 --> 00:13:02.844
This is what we wanted
to do with tango trees,

00:13:02.844 --> 00:13:04.510
but we weren't allowed
to because we had

00:13:04.510 --> 00:13:05.676
to be a binary search trees.

00:13:05.676 --> 00:13:07.420
And the keys were given to us.

00:13:07.420 --> 00:13:08.650
Here, there are no keys.

00:13:08.650 --> 00:13:11.320
So we need to specify them
and the most convenient one

00:13:11.320 --> 00:13:12.530
is by depth.

00:13:12.530 --> 00:13:19.790
So we're just taking a path
like this, 0, 1, 2, 3 4.

00:13:19.790 --> 00:13:23.470
And then we're turning it
into a nice balance tree

00:13:23.470 --> 00:13:33.430
like this, 0, 1, 2, 3, 3, 4.

00:13:33.430 --> 00:13:38.080
OK, Now, it's a splay
trees so it's not

00:13:38.080 --> 00:13:40.270
guaranteed to be
balanced at any moment,

00:13:40.270 --> 00:13:45.670
but amortized is going to have
log n performance preparation.

00:13:45.670 --> 00:13:48.280
OK, and then this
is sort of that's

00:13:48.280 --> 00:13:49.990
representing each of
these white paths,

00:13:49.990 --> 00:13:52.040
but then we also need
the red pointers.

00:13:52.040 --> 00:13:55.360
So what we're going
to do is say the root

00:13:55.360 --> 00:13:59.140
of each auxiliary
tree, I'll abbreviate

00:13:59.140 --> 00:14:08.410
ox tree, stores what I'll
call the path parent, which

00:14:08.410 --> 00:14:11.080
are these red pointers.

00:14:11.080 --> 00:14:25.240
The definition is this is, the
paths, the top nodes, parent,

00:14:25.240 --> 00:14:26.650
and represented tree.

00:14:33.220 --> 00:14:36.760
OK, very soon it's
going to get confusing

00:14:36.760 --> 00:14:38.710
and I'm going to always
make it explicit.

00:14:38.710 --> 00:14:40.780
Am I talking about the
represented tree the thing

00:14:40.780 --> 00:14:42.670
we're trying to represent?

00:14:42.670 --> 00:14:46.690
Or am I talking about auxiliary
trees because notion of parent

00:14:46.690 --> 00:14:48.700
is different in the two?

00:14:48.700 --> 00:14:50.770
So in an auxiliary
tree a parent is just

00:14:50.770 --> 00:14:54.010
whatever it happens to be
stored in the splay tree.

00:14:54.010 --> 00:14:56.710
When you splay operations
you care about those parents.

00:14:56.710 --> 00:14:59.830
When you're thinking
about the tree you're

00:14:59.830 --> 00:15:01.870
trying to represent,
you care about parents

00:15:01.870 --> 00:15:03.680
in the represented tree.

00:15:03.680 --> 00:15:04.930
Now, how do you see that here?

00:15:04.930 --> 00:15:09.124
Well following parent is like
doing predecessor over here.

00:15:09.124 --> 00:15:10.790
So we kind of know
how to do predecessor

00:15:10.790 --> 00:15:12.480
in a binary search tree.

00:15:12.480 --> 00:15:16.060
But when we get to 0,
which is the left most

00:15:16.060 --> 00:15:20.170
node in this tree, corresponds
to the top of the path,

00:15:20.170 --> 00:15:24.130
if we want to do the parent
that's going up from this path,

00:15:24.130 --> 00:15:26.580
that's going to be
the path parent.

00:15:26.580 --> 00:15:28.930
And it saying the
path's top node,

00:15:28.930 --> 00:15:32.620
that's this guy 0, its parent
and the representative tree

00:15:32.620 --> 00:15:34.240
are just going to
store that pointer.

00:15:34.240 --> 00:15:35.290
The only weird
thing is we're not

00:15:35.290 --> 00:15:37.090
going to store the
pointer here, we're

00:15:37.090 --> 00:15:40.420
going to store the pointer here.

00:15:40.420 --> 00:15:41.410
That's the path parent.

00:15:41.410 --> 00:15:43.750
We're going to put it at
the root of the splay tree,

00:15:43.750 --> 00:15:45.166
basically because
it's really easy

00:15:45.166 --> 00:15:46.510
to get to the root of a tree.

00:15:46.510 --> 00:15:48.400
You could probably
start here, you just

00:15:48.400 --> 00:15:51.180
have to go left every time
and it's kind of annoying.

00:15:51.180 --> 00:15:52.900
Analysis will get messier.

00:15:52.900 --> 00:15:54.940
So we'll put at the root.

00:15:54.940 --> 00:15:56.890
And so, in particular,
if I do a rotation,

00:15:56.890 --> 00:15:59.740
like if I rotate the tree like
this and make one the route,

00:15:59.740 --> 00:16:01.840
that path parent pointer
has to move to 1.

00:16:01.840 --> 00:16:03.580
But it's still
representing essentially

00:16:03.580 --> 00:16:05.680
for this whole splay
tree representing

00:16:05.680 --> 00:16:10.340
this path, what was the
parent pointer from there.

00:16:10.340 --> 00:16:13.690
So this is the represented
tree, and this is the ox tree.

00:16:16.600 --> 00:16:20.290
OK, now if I take all the
ox trees plus these parent

00:16:20.290 --> 00:16:25.180
pointers, I get something
called the tree of ox trees.

00:16:30.760 --> 00:16:34.450
And this is our representation.

00:16:34.450 --> 00:16:37.180
So there's the represented
thing versus our representation.

00:16:37.180 --> 00:16:39.471
I'm not going to use the word
representation because it

00:16:39.471 --> 00:16:41.200
sounds almost like represented.

00:16:41.200 --> 00:16:44.350
So it's going to be represented
versus tree of ox trees.

00:16:44.350 --> 00:16:45.940
Tree of ox trees
is what we store,

00:16:45.940 --> 00:16:48.670
represented is what
we want to store.

00:16:48.670 --> 00:16:51.700
That's what we're
trying to represent.

00:16:51.700 --> 00:16:57.160
So that's the
terminology, Basically, we

00:16:57.160 --> 00:16:59.080
want the tree of ox
trees to be balanced,

00:16:59.080 --> 00:17:01.413
and if there's splay trees,
they'll be kind of balanced.

00:17:04.390 --> 00:17:08.119
Whereas, the represented
tree is on balance.

00:17:08.119 --> 00:17:10.990
Cool so now I want
to give you some code

00:17:10.990 --> 00:17:13.201
and how we're going to
manipulate these things.

00:17:13.201 --> 00:17:14.950
And then we'll be able
to analyze the code

00:17:14.950 --> 00:17:17.619
and that both will
take a little while.

00:17:42.871 --> 00:17:44.620
The main operation I'm
going to talk about

00:17:44.620 --> 00:17:47.050
is actually just a
helper operation.

00:17:47.050 --> 00:17:52.820
So first I want to tell you
what it is, how it works.

00:17:52.820 --> 00:17:56.530
It's like an access
in a tango tree.

00:17:56.530 --> 00:18:00.100
With tango trees we just
wanted to touch item xi

00:18:00.100 --> 00:18:02.316
and then go onto the
next item, xi plus 1.

00:18:02.316 --> 00:18:03.940
So I'm going to think
about that world,

00:18:03.940 --> 00:18:06.275
while all I'm trying
to do is touch nodes.

00:18:06.275 --> 00:18:07.900
What's interesting
about touching nodes

00:18:07.900 --> 00:18:12.590
is it changes this notion
of preferred edges.

00:18:12.590 --> 00:18:14.830
So, as I said, the last
access in that subtree

00:18:14.830 --> 00:18:16.340
was blah, blah, blah.

00:18:16.340 --> 00:18:17.110
So access.

00:18:19.690 --> 00:18:21.550
In reality, what I
mean is the last time

00:18:21.550 --> 00:18:26.560
that node was used as a link
or cut or find operation.

00:18:26.560 --> 00:18:28.660
But in fact I'm going
to make that explicit.

00:18:28.660 --> 00:18:31.630
Every operation is going to
start by calling this function

00:18:31.630 --> 00:18:33.850
access on its arguments.

00:18:33.850 --> 00:18:35.602
Question?

00:18:35.602 --> 00:18:37.498
AUDIENCE: I still
don't understand.

00:18:37.498 --> 00:18:41.710
When you say that this
[INAUDIBLE] by depth--

00:18:41.710 --> 00:18:42.646
PROFESSOR: Yes.

00:18:42.646 --> 00:18:44.229
AUDIENCE: How do you
go from that path

00:18:44.229 --> 00:18:45.930
to the actual splay tree?

00:18:45.930 --> 00:18:49.160
PROFESSOR: OK so the
transformation from this path

00:18:49.160 --> 00:18:50.950
in the represented
tree to splay tree

00:18:50.950 --> 00:18:55.750
is just these nodes have
depth within that path,

00:18:55.750 --> 00:18:57.850
I mean they're just
stored along the path.

00:18:57.850 --> 00:19:00.580
What I mean is, I want to store
them in as a binary search

00:19:00.580 --> 00:19:03.390
tree ordered by that value.

00:19:03.390 --> 00:19:06.100
So that's what-- yeah.

00:19:06.100 --> 00:19:08.420
So splay trees have
some key on the nodes,

00:19:08.420 --> 00:19:10.430
they maintain the binary
search tree property.

00:19:10.430 --> 00:19:11.971
My key is just going
to be the depth.

00:19:11.971 --> 00:19:13.144
The position along the path.

00:19:13.144 --> 00:19:15.352
AUDIENCE: So if you do an
in order traversal you just

00:19:15.352 --> 00:19:15.880
get the path.

00:19:15.880 --> 00:19:17.410
PROFESSOR: Right if I do
it in order traversal here,

00:19:17.410 --> 00:19:18.830
I'll get the path back.

00:19:18.830 --> 00:19:22.750
Yep, no problem.

00:19:22.750 --> 00:19:24.830
That's going to be
important to understand.

00:19:24.830 --> 00:19:29.600
OK, so to do an access, access
is going to do two things.

00:19:29.600 --> 00:19:31.930
The first thing it has to
do, and the other thing

00:19:31.930 --> 00:19:35.500
is going to make our
life easy, you'll

00:19:35.500 --> 00:19:39.080
see once we've defined access,
all operations become trivial.

00:19:39.080 --> 00:19:41.530
So it's going to be a
really cool helper function.

00:19:46.580 --> 00:19:49.570
The first thing we have to
do, when we access a node v,

00:19:49.570 --> 00:19:53.230
is say well that then by
definition the path to v from

00:19:53.230 --> 00:19:57.937
the root --v to root I guess,
sort of, but probably more root

00:19:57.937 --> 00:19:58.672
to v--

00:20:03.010 --> 00:20:03.940
should be preferred.

00:20:03.940 --> 00:20:05.440
That's the definition
of preferred

00:20:05.440 --> 00:20:07.231
because now it's the
latest thing accessed.

00:20:11.859 --> 00:20:12.900
So we've got to fix that.

00:20:15.265 --> 00:20:16.890
But we're going to
do a little bit more

00:20:16.890 --> 00:20:24.530
we're also going to make
v the root of its ox tree.

00:20:30.270 --> 00:20:33.060
Which will mean, because
that ox tree is now

00:20:33.060 --> 00:20:36.900
the top most ox tree because
that actually contains the root

00:20:36.900 --> 00:20:43.830
and it contains v. So
in fact, v is the root

00:20:43.830 --> 00:20:45.520
of the tree of ox trees.

00:20:45.520 --> 00:20:54.420
It's the overall root for
this tree of our streets.

00:20:54.420 --> 00:20:55.300
Why do we do that?

00:20:55.300 --> 00:20:58.047
Well, it's sort of going to
just be a consequence of using

00:20:58.047 --> 00:20:59.880
splay, because whenever
you splice something

00:20:59.880 --> 00:21:04.020
you move it to the root
in this zigzaggy way.

00:21:04.020 --> 00:21:07.200
But it will actually be really
helpful to have this property,

00:21:07.200 --> 00:21:11.450
and that's why these are the
simplest link-cut trees I know.

00:21:11.450 --> 00:21:15.300
OK, so how do we do this?

00:21:15.300 --> 00:21:18.840
So you're given the node
v somewhere in this world,

00:21:18.840 --> 00:21:21.480
and we've basically got to
fix a lot of preferred child

00:21:21.480 --> 00:21:23.892
pointers.

00:21:23.892 --> 00:21:25.350
And, whereas, tango
trees basically

00:21:25.350 --> 00:21:30.420
walked from the top down,
navigating one preferred path

00:21:30.420 --> 00:21:32.070
until it found the
right place to exit

00:21:32.070 --> 00:21:35.220
and then fixing that edge, were
going to be working bottom up.

00:21:35.220 --> 00:21:38.010
Because we already know where
the vertexes, were given it,

00:21:38.010 --> 00:21:41.280
and we need to walk our way
up the tree and kind of push

00:21:41.280 --> 00:21:43.620
v to the root overall.

00:21:43.620 --> 00:21:50.040
So the first thing
to do is splay v. So

00:21:50.040 --> 00:21:56.990
that, now, when I say splay
v, I mean within its ox tree.

00:21:56.990 --> 00:22:00.650
Doesn't make sense to do
it in any global sense.

00:22:00.650 --> 00:22:04.060
In some sense access is going to
be our global version of splay.

00:22:04.060 --> 00:22:06.900
Whenever I say splay a node, I
mean just within its ox tree.

00:22:06.900 --> 00:22:08.900
That's going to be the
definition of splay tree.

00:22:08.900 --> 00:22:12.380
So you may recall from Lecture
Six there's the zig-zig case

00:22:12.380 --> 00:22:13.290
and zig-zag case.

00:22:13.290 --> 00:22:16.470
You do some rotation,
double rotation, whatever.

00:22:16.470 --> 00:22:18.840
In the end, maybe one
more rotation, and then v

00:22:18.840 --> 00:22:20.772
becomes the root.

00:22:20.772 --> 00:22:22.230
So what does the
picture look like?

00:22:22.230 --> 00:22:25.260
We've got v at the
root of it's ox tree.

00:22:25.260 --> 00:22:27.060
Then we've got things
in the left subtree

00:22:27.060 --> 00:22:29.461
which have smaller depth.

00:22:29.461 --> 00:22:31.710
And then we've got things
in the right subtree of tree

00:22:31.710 --> 00:22:34.260
which have bigger depth.

00:22:34.260 --> 00:22:38.620
Depth bigger than v. So we
just pulled to the root.

00:22:38.620 --> 00:22:43.350
So in the represented tree
what we have is a path v. These

00:22:43.350 --> 00:22:46.210
are things of smaller depth
these things of larger depth.

00:22:46.210 --> 00:22:50.100
Now, if you look at the
definition of preferred child,

00:22:50.100 --> 00:22:54.480
when we access v, v now no
longer has a preferred child.

00:22:54.480 --> 00:22:56.945
This preferred
child is now none.

00:22:56.945 --> 00:22:58.320
If you look at
this picture, this

00:22:58.320 --> 00:23:02.650
is a preferred path, currently,
v has a preferred child.

00:23:02.650 --> 00:23:03.870
We want to get rid of that.

00:23:03.870 --> 00:23:06.270
That's our first operation.

00:23:09.330 --> 00:23:12.390
First thing we want to do
is get rid of that edge.

00:23:12.390 --> 00:23:15.460
It's no longer a preferred edge.

00:23:15.460 --> 00:23:19.670
So that essentially
corresponds to this edge

00:23:19.670 --> 00:23:22.040
because that's the connection
from v to deeper things.

00:23:22.040 --> 00:23:24.800
I mean in fact, this
node right below us

00:23:24.800 --> 00:23:29.530
let's call it x is right here.

00:23:29.530 --> 00:23:31.880
It's the smallest
depth among the nodes

00:23:31.880 --> 00:23:33.860
with larger depth than v.

00:23:33.860 --> 00:23:36.080
But if we kind of
kill that connection,

00:23:36.080 --> 00:23:39.720
then, now, this path is its
own thing, the part below v,

00:23:39.720 --> 00:23:42.120
separate from v and above.

00:23:42.120 --> 00:23:44.210
So that's what we're
going to do first.

00:23:44.210 --> 00:23:49.340
Remove these preferred child.

00:23:53.510 --> 00:23:56.092
And I'm going to elaborate
exactly the point arithmetic

00:23:56.092 --> 00:23:57.050
that makes that happen.

00:23:59.720 --> 00:24:03.770
This is the kind of tedious
part of, or really any point

00:24:03.770 --> 00:24:05.140
of machine data structure.

00:24:05.140 --> 00:24:07.640
This is going to all work on a
point of machine, by the way.

00:24:25.710 --> 00:24:29.860
OK, so basically I'm
obliterating the edge.

00:24:29.860 --> 00:24:35.770
So I'm going to make this
vertex here, have a path parent

00:24:35.770 --> 00:24:41.920
pointer to v and otherwise
obliterate this edge.

00:24:41.920 --> 00:24:45.160
It will no longer has a parent,
v no longer has a right child.

00:24:45.160 --> 00:24:50.680
So it's going to be v has a
left thing and no right pointer.

00:24:50.680 --> 00:24:55.485
But this separate tree is
going to a parent pointer to v.

00:24:55.485 --> 00:24:56.860
This is, of course,
if it exists.

00:24:56.860 --> 00:25:01.690
If v.right is nothing already,
then you don't do any of this.

00:25:01.690 --> 00:25:04.457
But if there is a right pointer
then you've got to do this.

00:25:04.457 --> 00:25:06.040
So this is the place
where we're going

00:25:06.040 --> 00:25:09.044
to set path parents,
pretty obvious stuff.

00:25:09.044 --> 00:25:10.960
The only thing to check
is that this is really

00:25:10.960 --> 00:25:11.751
in the right place.

00:25:11.751 --> 00:25:15.760
This thing is the root
of this ox tree, which

00:25:15.760 --> 00:25:18.790
is where the parent pointer
path parent supposed to be,

00:25:18.790 --> 00:25:22.450
and it points to v meaning,
that the parent of x

00:25:22.450 --> 00:25:24.220
is v in the represented tree.

00:25:24.220 --> 00:25:25.930
And that's exactly
what this picture is.

00:25:25.930 --> 00:25:29.410
This is the represented
tree parent of x is v,

00:25:29.410 --> 00:25:32.990
and so that's the correct
definition of pat parent.

00:25:32.990 --> 00:25:34.650
Cool.

00:25:34.650 --> 00:25:37.740
OK, now the fun part.

00:25:42.419 --> 00:25:43.960
Now, we're going to
walk up the tree.

00:25:46.891 --> 00:25:49.390
We've seen everything on the
outline except this heavy light

00:25:49.390 --> 00:25:50.640
decomposition.

00:25:50.640 --> 00:25:51.820
We'll come to that soon.

00:25:57.480 --> 00:26:01.900
OK, so now we're going
to walk up the tree

00:26:01.900 --> 00:26:05.710
and add new preferred
child pointers.

00:26:05.710 --> 00:26:09.070
This is the one that we
had to remove because it's

00:26:09.070 --> 00:26:12.940
the stuff below v. But up the
path, if we walk up to the root

00:26:12.940 --> 00:26:16.060
here, to the left
most node of v then

00:26:16.060 --> 00:26:17.530
there's a path
parent from there,

00:26:17.530 --> 00:26:21.330
we want to make that not a path
parent but a regular parent.

00:26:21.330 --> 00:26:23.500
Because that right
now, is living

00:26:23.500 --> 00:26:25.690
in its own little
preferred path that we

00:26:25.690 --> 00:26:29.230
want that preferred path to
extend all the way to the root,

00:26:29.230 --> 00:26:33.050
by the definition of a
child after doing an access.

00:26:33.050 --> 00:26:42.940
So we're going to do a loop
until v path parent is none.

00:26:48.800 --> 00:26:52.950
I'm going to let w
be v's path parent.

00:26:57.470 --> 00:26:59.700
save some writing.

00:26:59.700 --> 00:27:02.170
And then we're going to splay w.

00:27:02.170 --> 00:27:05.540
OK, I think at this point,
I should draw a picture.

00:27:05.540 --> 00:27:15.020
So many pictures to draw.

00:27:15.020 --> 00:27:21.610
So we have, let's say, a
node w as a child v. This

00:27:21.610 --> 00:27:25.120
is the represented tree.

00:27:25.120 --> 00:27:30.370
That's some other child x
and I can have many children.

00:27:30.370 --> 00:27:34.060
Let's suppose that, right now,
the preferred child from w

00:27:34.060 --> 00:27:35.890
is x.

00:27:35.890 --> 00:27:38.560
It's not v because we just
followed a path parent pointer

00:27:38.560 --> 00:27:42.940
to go from v's path, which is
something here, to w's path.

00:27:42.940 --> 00:27:45.850
So w's path is going to
be something like this.

00:27:45.850 --> 00:27:48.490
So it goes to some
other guy x, we

00:27:48.490 --> 00:27:51.610
want change that that pointer.

00:27:51.610 --> 00:27:56.160
Instead of being that,
we want to go here.

00:27:56.160 --> 00:27:58.000
That's in the represented tree.

00:27:58.000 --> 00:28:03.610
Now what does this look like
in the tree of ox trees?

00:28:03.610 --> 00:28:05.340
W lives in some thing.

00:28:09.760 --> 00:28:14.260
w's there, x's its
successor in there,

00:28:14.260 --> 00:28:19.720
so maybe it's like a
right child or whatever,

00:28:19.720 --> 00:28:21.250
somewhere else in the tree.

00:28:21.250 --> 00:28:24.210
And then separately we've
already built this thing.

00:28:24.210 --> 00:28:28.210
v it has a left child, it has
no right child because there's

00:28:28.210 --> 00:28:32.680
nothing deeper than v in
its own preferred path.

00:28:32.680 --> 00:28:35.950
And then we have a path parent
pointer that goes like this.

00:28:40.070 --> 00:28:40.860
I want to fix.

00:28:40.860 --> 00:28:42.860
That the first thing I'm
going to do is splay w,

00:28:42.860 --> 00:28:46.070
so the w is in the
root of its own tree.

00:28:46.070 --> 00:28:50.480
So then it's going
to look like w.

00:28:50.480 --> 00:28:54.110
It's going to have a left child,
left subtree, right subtree.

00:28:54.110 --> 00:28:56.360
X is going to be its
successor so it's

00:28:56.360 --> 00:28:58.640
the leftmost thing in there.

00:28:58.640 --> 00:29:06.020
And we still have v with its
left child and this pointer.

00:29:06.020 --> 00:29:07.110
It's not in the tree.

00:29:07.110 --> 00:29:10.250
So if two ox trees, now I want
to basically merge these two ox

00:29:10.250 --> 00:29:13.880
trees, but also get
rid of this stuff.

00:29:13.880 --> 00:29:15.350
Just like we did
up here actually.

00:29:15.350 --> 00:29:18.620
First, I have to destroy
this preferred child

00:29:18.620 --> 00:29:20.780
and then make a new
one, which is v.

00:29:20.780 --> 00:29:21.530
So how do I do it?

00:29:21.530 --> 00:29:23.960
I just replace the
right pointer from w

00:29:23.960 --> 00:29:29.480
to be v instead of whatever
this thing is that's it.

00:29:29.480 --> 00:29:42.110
So say, switch w's preferred
child to be v. And what we do

00:29:42.110 --> 00:29:51.440
is say w, first we clip
off the existing guy,

00:29:51.440 --> 00:29:57.110
we say this node's w.rights path
parent is now going to be w.

00:29:57.110 --> 00:29:59.900
We still want to have some way
to get from here back up to w,

00:29:59.900 --> 00:30:01.640
just like we did up here.

00:30:01.640 --> 00:30:04.530
This code is going to look very
similar to these two lines.

00:30:04.530 --> 00:30:05.825
We set it's parents to none.

00:30:09.300 --> 00:30:13.560
And we set w.right.

00:30:13.560 --> 00:30:15.470
Up, here we set it to none.

00:30:15.470 --> 00:30:18.230
Now we know it
actually needs to be v.

00:30:18.230 --> 00:30:19.880
And then we set
the reverse pointer

00:30:19.880 --> 00:30:26.150
so v's parent is now w and v
no longer has a path parent.

00:30:31.920 --> 00:30:35.900
So essentially the reverse
of these operations.

00:30:35.900 --> 00:30:38.450
So we remove this
preferred child pointer

00:30:38.450 --> 00:30:39.770
and we add this one in.

00:30:39.770 --> 00:30:44.840
So the new picture will be,
we have w has its left subtree

00:30:44.840 --> 00:30:46.250
just like before.

00:30:46.250 --> 00:30:49.770
It's right subtree is now
v with its left subtree.

00:30:49.770 --> 00:30:53.210
And then we also have this
other tree hanging out.

00:30:53.210 --> 00:30:57.219
Not directly connected except
by path parent pointer.

00:30:57.219 --> 00:30:59.510
So whereas before, v was
linked in with the path parent

00:30:59.510 --> 00:31:01.926
pointer, now this thing is
linked to in the parent pointer

00:31:01.926 --> 00:31:03.680
and sort of the
primary connection,

00:31:03.680 --> 00:31:07.670
the white connection
is direct from w to v.

00:31:07.670 --> 00:31:09.470
And that's exactly
what corresponds

00:31:09.470 --> 00:31:11.730
to clipping off this portion
of the preferred path

00:31:11.730 --> 00:31:16.330
and concatenating on this
portion of the preferred path.

00:31:16.330 --> 00:31:17.600
More or less clear?

00:31:17.600 --> 00:31:19.450
You can double
check this at home

00:31:19.450 --> 00:31:23.754
but that's what we need to, do.

00:31:23.754 --> 00:31:25.670
To go back and forth
between these two worlds.

00:31:25.670 --> 00:31:28.969
The represented world
and the tree of our world

00:31:28.969 --> 00:31:30.010
is doing the right thing.

00:31:30.010 --> 00:31:34.620
Again you can check that
this path parent is, indeed,

00:31:34.620 --> 00:31:35.410
the right thing.

00:31:35.410 --> 00:31:37.330
It's essentially saying
the parent of x equals

00:31:37.330 --> 00:31:39.890
w, which is, indeed, the case.

00:31:39.890 --> 00:31:45.640
That left most thing
here, its parent is w.

00:31:45.640 --> 00:31:51.730
Cool last thing we do is
kind of a lame way to say it,

00:31:51.730 --> 00:31:55.360
but I want to splay v
within its ox tree Now,

00:31:55.360 --> 00:31:56.720
v is a child of the root.

00:31:56.720 --> 00:32:01.290
So this just means
rotate v. So what

00:32:01.290 --> 00:32:05.800
it's going to look like
is v becomes the root,

00:32:05.800 --> 00:32:10.690
it's left child is w, that
left child is whatever,

00:32:10.690 --> 00:32:12.330
that right child is whatever.

00:32:12.330 --> 00:32:15.554
V will still have no right
child because v is the deepest

00:32:15.554 --> 00:32:16.720
node in it's preferred path.

00:32:16.720 --> 00:32:17.890
So there's nothing
deeper than it.

00:32:17.890 --> 00:32:19.510
There's nothing
to the right of v.

00:32:19.510 --> 00:32:22.010
So these two
triangles go to here.

00:32:22.010 --> 00:32:24.520
Of course, there's still the
old triangle with x in it,

00:32:24.520 --> 00:32:27.500
and it's still going to prefer
it's still going to point to w.

00:32:30.040 --> 00:32:31.660
But we want v to
eventually end up

00:32:31.660 --> 00:32:35.860
to be the very, very root so
I'd like to make the root again

00:32:35.860 --> 00:32:39.450
after I did this concatenation.

00:32:39.450 --> 00:32:43.260
And so there you go you can
think of this as a second splay

00:32:43.260 --> 00:32:50.170
if you want or as a
rotation, either way.

00:32:50.170 --> 00:32:52.040
And now we're going to loop.

00:32:52.040 --> 00:32:54.820
OK, the one thing I
didn't make explicit

00:32:54.820 --> 00:32:58.870
is that when we do a splay,
or when we do a rotation,

00:32:58.870 --> 00:33:02.650
you have to carry along
the path parent pointer.

00:33:02.650 --> 00:33:05.830
So like right now,
sorry, in this picture,

00:33:05.830 --> 00:33:07.690
w has some path parent
pointer because it's

00:33:07.690 --> 00:33:09.340
the root of its ox tree.

00:33:09.340 --> 00:33:11.399
After we do the
rotation, v is the root

00:33:11.399 --> 00:33:13.690
and so it's going to have
the parent path parent point.

00:33:13.690 --> 00:33:18.770
Or you can just define rotate
to preserve that information.

00:33:18.770 --> 00:33:22.030
So now v has some new path
parent and we do the loop.

00:33:22.030 --> 00:33:24.650
As long as it is not
there's something there,

00:33:24.650 --> 00:33:27.700
we're going to splay
it stick them together.

00:33:27.700 --> 00:33:30.490
Repeat, the number
of times we repeat,

00:33:30.490 --> 00:33:34.042
is equal to the number of
preferred child changes.

00:33:34.042 --> 00:33:36.000
So that's how we're going
to analyze the thing.

00:33:36.000 --> 00:33:41.020
How many times does a child
have to change in this world.

00:33:41.020 --> 00:33:47.410
OK, clear, more or
less that is that's

00:33:47.410 --> 00:33:49.630
the hard the hard
operation access.

00:33:52.960 --> 00:33:56.290
One thing to note is v will
have no right child at the end,

00:33:56.290 --> 00:33:59.410
and it will be the root
of the tree of ox trees.

00:33:59.410 --> 00:34:01.240
Why the tree of ox trees?

00:34:01.240 --> 00:34:03.490
When we stop, we
have no path parent.

00:34:03.490 --> 00:34:05.720
That means we are
the overall root.

00:34:05.720 --> 00:34:06.610
So that's the end.

00:34:09.570 --> 00:34:14.830
Cool now let me
tell you how to do--

00:34:14.830 --> 00:34:16.710
first, I'll do the
queries, and then I'll

00:34:16.710 --> 00:34:17.989
do the updates, link-cut.

00:34:17.989 --> 00:34:20.590
Cut Make tree, I'm pretty
sure, if you all think

00:34:20.590 --> 00:34:22.440
you know how did you make tree.

00:34:22.440 --> 00:34:24.020
So let's start with find root.

00:34:28.530 --> 00:34:36.150
So for find root, first thing
we're going to do is access v.

00:34:36.150 --> 00:34:42.750
So what that gives us is v, no
right child, some left child.

00:34:42.750 --> 00:34:47.489
This is v's ox tree, but the
roots of the overall tree

00:34:47.489 --> 00:34:48.949
is right here.

00:34:48.949 --> 00:34:49.530
This is r.

00:34:52.060 --> 00:34:54.610
Because, in the
end, we know that,

00:34:54.610 --> 00:34:58.150
the mean the root ox tree
always contains the root

00:34:58.150 --> 00:35:02.010
node of the tree, and the
access operation makes it also

00:35:02.010 --> 00:35:09.400
contain v So what's the highest
node in that path from r to v?

00:35:09.400 --> 00:35:11.590
Well, it's the left
most node in the thing.

00:35:11.590 --> 00:35:20.650
So you just block left
to find the root r.

00:35:20.650 --> 00:35:24.546
And then, we are going to do
one more thing, which splay r.

00:35:24.546 --> 00:35:26.410
If we didn't splay
r, we'd be in trouble

00:35:26.410 --> 00:35:28.450
because this is a splay tree.

00:35:28.450 --> 00:35:32.360
If you say this r might be
extremely deep in the tree.

00:35:32.360 --> 00:35:34.510
And so if you just repeatedly
said, find root of v,

00:35:34.510 --> 00:35:36.730
find v for the same
v, you don't want

00:35:36.730 --> 00:35:39.940
to have to walk down linear
length path every single time.

00:35:39.940 --> 00:35:43.870
So we're going to splay it
every time we touch the root,

00:35:43.870 --> 00:35:47.500
so that very soon r will be
near the root of the tree of ox

00:35:47.500 --> 00:35:49.520
trees, and so this
operation will become fast.

00:35:49.520 --> 00:35:52.150
So amortized it will
always be order log n.

00:35:52.150 --> 00:35:54.970
But we need to do that.

00:35:54.970 --> 00:35:57.700
OK that's fine root.

00:35:57.700 --> 00:35:59.606
Let's do half aggregate.

00:36:05.570 --> 00:36:08.440
Of aggregates
basically the same.

00:36:08.440 --> 00:36:09.910
Actually, even easier.

00:36:09.910 --> 00:36:12.040
First thing we do like
all of our operations,

00:36:12.040 --> 00:36:16.270
is access v, so we
get that picture.

00:36:16.270 --> 00:36:18.700
So remember what
this corresponds to?

00:36:18.700 --> 00:36:26.026
This is an ox tree that
represents a path ending in v

00:36:26.026 --> 00:36:29.860
So this is in the
represented tree.

00:36:29.860 --> 00:36:31.840
And the goal of a
path aggregate is

00:36:31.840 --> 00:36:35.480
to compute the min or the max
or to some of those things.

00:36:35.480 --> 00:36:37.450
So I basically
have this tree that

00:36:37.450 --> 00:36:39.970
represents exactly the
things I care about,

00:36:39.970 --> 00:36:43.780
and I just need to do a sum
or a min or a max or whatever.

00:36:43.780 --> 00:36:46.390
So easy way to do it is
augment all the ox trees

00:36:46.390 --> 00:36:48.640
to have subtree
size, subtree sums,

00:36:48.640 --> 00:36:51.860
or mins or maxes, whatever
operations you care about.

00:36:51.860 --> 00:37:03.510
And so then it's just a return
v.subtree min max, whatever.

00:37:08.230 --> 00:37:10.707
You have to have to check
when we do link-cuts

00:37:10.707 --> 00:37:12.790
that it's easy to maintain
augmentation like this,

00:37:12.790 --> 00:37:13.930
but it is.

00:37:13.930 --> 00:37:17.200
And now this, the
subtree aggregations

00:37:17.200 --> 00:37:19.030
are relative to
your own ox tree.

00:37:19.030 --> 00:37:20.741
You don't go deeper.

00:37:20.741 --> 00:37:22.240
In fact, there's
no way to go deeper

00:37:22.240 --> 00:37:24.380
because if you look
at the structure,

00:37:24.380 --> 00:37:25.540
there's no way to go down.

00:37:25.540 --> 00:37:27.100
We store these path
parents, but we

00:37:27.100 --> 00:37:29.950
can't afford to store path
children because a node may

00:37:29.950 --> 00:37:32.050
have a zillion path children.

00:37:32.050 --> 00:37:34.600
So it's kind of
awkward to store them.

00:37:34.600 --> 00:37:37.900
we don't have to because
this aggregation is just

00:37:37.900 --> 00:37:38.956
within the ox tree.

00:37:38.956 --> 00:37:40.330
That's exactly
what we care about

00:37:40.330 --> 00:37:44.120
because it represents that
path and nothing more.

00:37:44.120 --> 00:37:48.670
So you see, access makes
our life pretty darn easy.

00:37:48.670 --> 00:37:50.650
Once that path is preferred,
we can do whatever

00:37:50.650 --> 00:37:51.760
we need to with that path.

00:37:51.760 --> 00:37:56.350
We can compute aggregations,
the root, anything pretty

00:37:56.350 --> 00:37:58.255
much instantly once
we have access.

00:38:00.790 --> 00:38:04.240
OK, I claim also link
and cut are really easy.

00:38:08.060 --> 00:38:11.210
So let me show you that.

00:38:11.210 --> 00:38:12.230
So let's start with cut.

00:38:16.060 --> 00:38:23.320
First thing we do, you
guessed it, access v. So

00:38:23.320 --> 00:38:24.940
think about this
picture a little bit.

00:38:24.940 --> 00:38:28.900
So we have v, have this stuff.

00:38:28.900 --> 00:38:31.520
What this corresponds
to, this is the ox tree

00:38:31.520 --> 00:38:33.250
in the represented tree.

00:38:33.250 --> 00:38:37.090
This is a path
from the root to v.

00:38:37.090 --> 00:38:39.280
And our goal in
the cut operation

00:38:39.280 --> 00:38:42.700
is to separate v from its
parent in the represented tree.

00:38:42.700 --> 00:38:46.840
So we want to remove this
edge above v. That basically

00:38:46.840 --> 00:38:48.970
corresponds to this edge.

00:38:48.970 --> 00:38:52.210
Connection from v to all the
things less deep than it.

00:38:52.210 --> 00:38:53.530
So this is the preferred path.

00:38:53.530 --> 00:38:57.040
Of course, in reality, there
is some subtree down here,

00:38:57.040 --> 00:38:59.990
and that's going to correspond
to things that are linked here

00:38:59.990 --> 00:39:02.030
by path parent pointers.

00:39:02.030 --> 00:39:05.410
So they'll come along for the
ride, because what they know

00:39:05.410 --> 00:39:09.310
is they're attached to v.
And so all we need to do

00:39:09.310 --> 00:39:11.650
is delete this edge
and we're done.

00:39:11.650 --> 00:39:17.450
It's kind of crazy,
but it works.

00:39:17.450 --> 00:39:27.550
So what we do, say, v
left the parent is none.

00:39:27.550 --> 00:39:31.870
The left is none.

00:39:31.870 --> 00:39:32.860
That's it.

00:39:32.860 --> 00:39:33.830
Gone.

00:39:33.830 --> 00:39:36.100
That edge has disappeared.

00:39:36.100 --> 00:39:40.405
What will be left with
is v all by itself.

00:39:40.405 --> 00:39:42.970
/ Has no left child,
no right child.

00:39:42.970 --> 00:39:48.070
It still has some things that
link into it via path parent

00:39:48.070 --> 00:39:49.940
pointers.

00:39:49.940 --> 00:39:56.500
But v is alone in its ox
tree after you do a cut.

00:39:56.500 --> 00:39:59.860
This thing will now live
in a separate world.

00:39:59.860 --> 00:40:03.760
In particular, this node
becomes the new root

00:40:03.760 --> 00:40:06.860
of the tree of ox
trees for this tree.

00:40:06.860 --> 00:40:08.770
after we do the cut,
there's two trees.

00:40:08.770 --> 00:40:10.150
So there's two
trees of ox trees.

00:40:10.150 --> 00:40:12.250
There's the one with v,
v will remain the root

00:40:12.250 --> 00:40:14.200
of its tree of ox trees.

00:40:14.200 --> 00:40:17.950
And the other one,
this thing called x,

00:40:17.950 --> 00:40:21.720
becomes its own root of
its own tree of ox trees.

00:40:21.720 --> 00:40:23.130
So there's nothing else to do.

00:40:23.130 --> 00:40:25.270
It doesn't need a parent
pointer because it's not

00:40:25.270 --> 00:40:28.230
linked to anything above it.

00:40:28.230 --> 00:40:30.910
The end.

00:40:30.910 --> 00:40:33.740
OK, I corresponds to
some node up here.

00:40:33.740 --> 00:40:34.840
Kind of the median node.

00:40:39.130 --> 00:40:40.550
So there you go.

00:40:40.550 --> 00:40:41.570
That's a cut.

00:40:41.570 --> 00:40:43.832
It's like super short code.

00:40:43.832 --> 00:40:45.290
You have to stare
at it for a while

00:40:45.290 --> 00:40:49.940
and make sure it does all the
right things, but it does.

00:40:49.940 --> 00:40:51.240
How about a link?

00:40:51.240 --> 00:40:54.999
Well first thing we do on a
link, is access v and access w.

00:40:54.999 --> 00:40:56.540
These don't interfere
with each other

00:40:56.540 --> 00:40:59.170
because precondition
is that v and w are

00:40:59.170 --> 00:41:01.360
in different trees of ox trees.

00:41:01.360 --> 00:41:04.520
They're indifferent
represented trees.

00:41:04.520 --> 00:41:06.170
So they're completely
independent.

00:41:06.170 --> 00:41:08.150
The result will
be that we have--

00:41:15.030 --> 00:41:18.790
should be consistent --so
ox trees are on the left.

00:41:18.790 --> 00:41:22.690
We're going to have w, is
going to have a left thing.

00:41:22.690 --> 00:41:27.010
We're going to have v claim
all by itself because remember

00:41:27.010 --> 00:41:28.540
what a link does?

00:41:28.540 --> 00:41:31.390
It's right here, v is
assumed to be a root node.

00:41:31.390 --> 00:41:34.030
So if you do an access
on the root node,

00:41:34.030 --> 00:41:36.840
then the path from the root
to v is a very short path.

00:41:36.840 --> 00:41:38.630
It is just v itself.

00:41:38.630 --> 00:41:40.330
So the ox tree
containing v, will just

00:41:40.330 --> 00:41:46.060
be v itself when you
do x as v. Yeah, so

00:41:46.060 --> 00:41:50.005
this is the picture
in represented space.

00:41:50.005 --> 00:41:51.880
And so we access v,
we're going to have this.

00:41:51.880 --> 00:41:53.790
Of course, there's
stuff pointing into it.

00:41:53.790 --> 00:41:56.770
We're at access w, so it's
going to look like this.

00:41:56.770 --> 00:42:00.244
And then this path is going
to be what's over here.

00:42:00.244 --> 00:42:01.660
And there's, of
course, more stuff

00:42:01.660 --> 00:42:03.880
linked from below into those.

00:42:03.880 --> 00:42:08.050
Our goal is to add this
edge between v and w, which

00:42:08.050 --> 00:42:10.660
corresponds to
adding this change.

00:42:15.050 --> 00:42:18.540
So that's what
we're going to do.

00:42:18.540 --> 00:42:20.278
V.left left equals w.

00:42:23.086 --> 00:42:29.920
W.parent equals v.

00:42:29.920 --> 00:42:34.210
If you want, you could instead
make v the right child of w.

00:42:34.210 --> 00:42:35.740
And that looks much more sane.

00:42:35.740 --> 00:42:38.390
I like it this way because
it looks kind of insane.

00:42:38.390 --> 00:42:39.929
This is not unbalanced
or anything.

00:42:39.929 --> 00:42:42.220
But splay trees will fix it
so you don't have to worry.

00:42:42.220 --> 00:42:45.490
This is the carefree
approach to data structuring.

00:42:45.490 --> 00:42:47.830
And you just leave it to
the analysis to make sure.

00:42:47.830 --> 00:42:52.060
Everything here is going
to be log n amortized.

00:42:52.060 --> 00:42:56.170
But you can check this is doing
the right thing, because v

00:42:56.170 --> 00:42:57.780
is deeper than w, right?

00:42:57.780 --> 00:43:01.250
So we had this path from
the root over here to w.

00:43:01.250 --> 00:43:03.884
We're extending the
path by one node, v,

00:43:03.884 --> 00:43:05.800
and so v should be to
the right of everything.

00:43:05.800 --> 00:43:08.140
So either it goes that
here is that right child

00:43:08.140 --> 00:43:11.110
w that would also work, or
would make it the parent of w

00:43:11.110 --> 00:43:13.280
on the right that works.

00:43:13.280 --> 00:43:16.750
It's in the correct order,
binary search tree order.

00:43:16.750 --> 00:43:18.220
OK?

00:43:18.220 --> 00:43:20.475
So you see length and
links and cuts are easy.

00:43:20.475 --> 00:43:21.850
In fact, the most
complicated was

00:43:21.850 --> 00:43:25.690
find root where we had
to do a walk and splay,

00:43:25.690 --> 00:43:28.360
but basically, everything
reduces to access.

00:43:28.360 --> 00:43:30.910
If access is fast,
all these operations

00:43:30.910 --> 00:43:33.970
will be fast because they
spend essentially constant time

00:43:33.970 --> 00:43:36.365
plus a constant
number of accesses.

00:43:36.365 --> 00:43:37.240
Except for find root.

00:43:37.240 --> 00:43:38.290
It also doesn't splay.

00:43:38.290 --> 00:43:40.373
But we're going to show
displays are efficient as,

00:43:40.373 --> 00:43:44.010
well as part of access, because
access does a ton of splays.

00:43:44.010 --> 00:43:45.550
So this is log n
amortize, surely

00:43:45.550 --> 00:43:47.290
one splay is log n amortized.

00:43:47.290 --> 00:43:50.300
And indeed, that
will be the case.

00:43:50.300 --> 00:43:53.800
AUDIENCE: Splay as access.

00:43:53.800 --> 00:43:56.680
PROFESSOR: Here, I'm treating
splaying not as an access.

00:43:56.680 --> 00:44:00.569
So I'm going to define access
to mean calling this function.

00:44:00.569 --> 00:44:01.976
AUDIENCE: [INAUDIBLE].

00:44:07.140 --> 00:44:10.250
PROFESSOR: OK so over
here, access first splays v

00:44:10.250 --> 00:44:11.470
and displays various things.

00:44:11.470 --> 00:44:13.914
It might not splay r.

00:44:13.914 --> 00:44:17.650
AUDIENCE: No, I'm saying, do
you call access r [INAUDIBLE]?

00:44:17.650 --> 00:44:19.270
PROFESSOR: Oh good.

00:44:19.270 --> 00:44:21.160
That might simplify my analysis.

00:44:21.160 --> 00:44:25.540
I'll just change this
line to access r.

00:44:25.540 --> 00:44:28.390
Good, why not?

00:44:31.060 --> 00:44:32.980
Yeah, that seems
like a good way.

00:44:36.400 --> 00:44:38.350
OK, I think you could do that.

00:44:38.350 --> 00:44:41.410
It might simplify,
conceptually, what's going on.

00:44:41.410 --> 00:44:45.410
The one thing I find
annoying about it's just--

00:44:45.410 --> 00:44:47.050
it's an aesthetic, let's say.

00:44:47.050 --> 00:44:50.260
So here, I was talking
about the last access.

00:44:50.260 --> 00:44:53.800
And if you define lost access
to mean access, that's fine.

00:44:53.800 --> 00:44:56.170
But also another intuitive
notion of the last access,

00:44:56.170 --> 00:44:59.650
is the last time it was given to
any of these functions cut link

00:44:59.650 --> 00:45:01.520
find root path aggregate.

00:45:01.520 --> 00:45:03.942
And so r is not really
given to the function.

00:45:03.942 --> 00:45:05.650
Of course, it's the
output of find roots,

00:45:05.650 --> 00:45:07.840
so maybe you think
of that as an access.

00:45:07.840 --> 00:45:10.270
You could say find root
is accessing the root.

00:45:10.270 --> 00:45:13.680
Either way, this
should work either way,

00:45:13.680 --> 00:45:15.660
but I think I like that.

00:45:15.660 --> 00:45:19.190
You just have to
redefine things a little.

00:45:19.190 --> 00:45:21.250
OK, let's do some analysis.

00:45:21.250 --> 00:45:22.990
This is the data structure.

00:45:22.990 --> 00:45:25.280
Algorithms are all up there
in they're gory detail.

00:45:25.280 --> 00:45:25.780
This is.

00:45:25.780 --> 00:45:26.260
Of course.

00:45:26.260 --> 00:45:26.760
goriest.

00:45:34.604 --> 00:45:40.130
I can now erase the, API.

00:45:53.780 --> 00:45:57.290
Makes me think of
Google versus Oracle.

00:45:57.290 --> 00:45:59.180
And then following that case?

00:45:59.180 --> 00:46:02.278
Yeah, it's interesting.

00:46:06.190 --> 00:46:23.590
OK pretty clear
this implementation

00:46:23.590 --> 00:46:26.360
is much more significant
than the API, but anyway.

00:46:26.360 --> 00:46:28.120
If

00:46:28.120 --> 00:46:30.190
First goal is to
prove log squared.

00:46:30.190 --> 00:46:31.840
This is just like a warm up.

00:46:31.840 --> 00:46:33.622
This is actually
trivial at this point.

00:46:33.622 --> 00:46:35.830
We've done all the work to
do a lot of squared bound.

00:46:35.830 --> 00:46:37.454
In fact, you just
replace the slay tree

00:46:37.454 --> 00:46:39.670
with a red-black
tree, and you know

00:46:39.670 --> 00:46:44.380
that each of these
operations is Log n.

00:46:44.380 --> 00:46:47.140
All displays that we do, I
mean, you can do essentially

00:46:47.140 --> 00:46:49.754
like a splay in a balance
binary [INAUDIBLE] tree,

00:46:49.754 --> 00:46:51.170
you can still move
it to the root.

00:46:51.170 --> 00:46:54.070
You can still maintain it
temporarily and maintain

00:46:54.070 --> 00:46:55.237
the height is order log n.

00:46:55.237 --> 00:46:56.320
That's one way to view it.

00:46:56.320 --> 00:46:58.652
Or you can observe the
splay tree analysis

00:46:58.652 --> 00:47:00.610
that gives you log n,
which we haven't actually

00:47:00.610 --> 00:47:02.140
covered in this class.

00:47:02.140 --> 00:47:03.520
Still applies in this scenario.

00:47:03.520 --> 00:47:05.103
Even though it's not
one splay a tree.

00:47:05.103 --> 00:47:06.490
It's a bunch of trees.

00:47:06.490 --> 00:47:09.220
You can show each of the
splays is order log n.

00:47:09.220 --> 00:47:13.900
So what that gives you is that--

00:47:13.900 --> 00:47:18.285
so we have lets just say
it's order log n amortized

00:47:18.285 --> 00:47:22.680
per splay, a few splay trees
or use regular balancer

00:47:22.680 --> 00:47:24.690
trees is definitely log n.

00:47:24.690 --> 00:47:33.220
So then if we do m operations,
it's going to cost --we're not

00:47:33.220 --> 00:47:35.020
actually going to be done--

00:47:35.020 --> 00:47:41.680
order log n times
m plus total number

00:47:41.680 --> 00:47:43.045
of preferred child changes.

00:47:54.400 --> 00:47:58.150
This bound should be clear,
because every operation reduces

00:47:58.150 --> 00:48:02.170
to accesses plus
constant amount of work.

00:48:02.170 --> 00:48:07.070
Maybe one more splay a
splay is just another log n.

00:48:07.070 --> 00:48:15.100
And the total number of
preferred child changes

00:48:15.100 --> 00:48:16.920
comes from this access thing.

00:48:16.920 --> 00:48:20.609
We're doing one splay per
preferred child change.

00:48:20.609 --> 00:48:22.150
So that thing is
reasonable, you just

00:48:22.150 --> 00:48:24.640
take it, multiply by
log n, we're done.

00:48:24.640 --> 00:48:28.810
So the remaining thing is,
at this point, just claim.

00:48:28.810 --> 00:48:34.700
Total number of preferred
trial changes is order m log n.

00:48:34.700 --> 00:48:38.470
So if you take this
whole thing, divide by m,

00:48:38.470 --> 00:48:41.740
you get log squared amortize.

00:48:41.740 --> 00:48:44.380
So that sounds kind
of lame, log square

00:48:44.380 --> 00:48:46.847
is not such a good bound,
but it's a warm up.

00:48:46.847 --> 00:48:48.430
In fact, we need to
prove this anyway.

00:48:48.430 --> 00:48:50.090
We need this for
the log n analysis.

00:48:50.090 --> 00:48:51.640
So first thing
I'm going to do is

00:48:51.640 --> 00:48:56.020
prove total number of preferred
child changes is log squared.

00:48:56.020 --> 00:48:59.510
Before I do that, I need
heavy-light decomposition.

00:48:59.510 --> 00:49:02.140
So to prove, this we're going to
use heavy-light decomposition.

00:49:02.140 --> 00:49:04.223
And this I think, is where
things get pretty cool.

00:49:22.440 --> 00:49:25.320
So heavy-light
decomposition, this

00:49:25.320 --> 00:49:30.280
is another way to decompose
a tree into paths.

00:49:33.510 --> 00:49:35.250
So heavy-light
decomposition is, again,

00:49:35.250 --> 00:49:38.580
going to apply to
the represented tree.

00:49:38.580 --> 00:49:39.630
Not the tree of ox trees.

00:49:39.630 --> 00:49:42.930
It's like an intrinsic thing.

00:49:42.930 --> 00:49:47.340
It's very simple we define
the size of the node

00:49:47.340 --> 00:49:50.340
to be the number of
nodes in that subtree.

00:49:50.340 --> 00:49:52.740
We've done this
many times, I think.

00:49:58.140 --> 00:50:04.560
And then, we're going
to call an edge from v

00:50:04.560 --> 00:50:14.150
to its parent heavy or light.

00:50:14.150 --> 00:50:23.020
It's heavy if the size
of v is more than half

00:50:23.020 --> 00:50:24.375
of the size of its parent.

00:50:32.164 --> 00:50:33.580
And, otherwise,
it's called light.

00:50:41.570 --> 00:50:45.640
OK, so we have parent
and sub child v

00:50:45.640 --> 00:50:47.990
has loads of other children.

00:50:47.990 --> 00:50:51.080
I just want to know, is the
heaviest of all your children?

00:50:51.080 --> 00:50:52.910
That's one way to define it.

00:50:52.910 --> 00:50:55.010
But, in, particular
is a bigger than half

00:50:55.010 --> 00:50:56.859
of the total weight of p?

00:50:56.859 --> 00:50:58.400
So there might not
be any heavy child

00:50:58.400 --> 00:50:59.608
according to this definition.

00:50:59.608 --> 00:51:01.700
Maybe it's nicely
evenly balanced.

00:51:01.700 --> 00:51:03.090
Everybody's got a third.

00:51:03.090 --> 00:51:05.540
But if somebody has got bigger
than 1/2, I call it heavy.

00:51:05.540 --> 00:51:06.620
Everybody else is light.

00:51:06.620 --> 00:51:10.490
So there's going to be, at most,
one heavy edge from every node.

00:51:10.490 --> 00:51:14.590
Therefore, heavy edges decompose
your world into path's.

00:51:14.590 --> 00:51:17.300
Heavy paths decompose the tree.

00:51:28.730 --> 00:51:34.100
Nodes, every node lives
in some heavy path.

00:51:34.100 --> 00:51:38.840
It may be node has no heavy
childs, but, at most, one.

00:51:38.840 --> 00:51:43.010
This may seem kind of silly,
but in fact, because your maybe

00:51:43.010 --> 00:51:43.880
all edges are light.

00:51:43.880 --> 00:51:45.640
This might not do
anything, every node

00:51:45.640 --> 00:51:49.160
is in its own path, that's
actually a really good case,

00:51:49.160 --> 00:51:51.080
light edges are good.

00:51:51.080 --> 00:51:51.830
Why are they good?

00:51:51.830 --> 00:51:55.130
Because then the size of
v is at most half the size

00:51:55.130 --> 00:51:56.190
of its parent.

00:51:56.190 --> 00:51:58.640
I mean, every time you
follow a light edge,

00:51:58.640 --> 00:52:01.350
the size of your subtree
went down by a factor of 2.

00:52:01.350 --> 00:52:02.930
How many times is
going to happen?

00:52:02.930 --> 00:52:04.310
Log n times.

00:52:04.310 --> 00:52:07.430
Start with everything at
the root, as you walk down,

00:52:07.430 --> 00:52:09.980
if you're decreasing your
side effect or two every time,

00:52:09.980 --> 00:52:12.140
you can only follow log .

00:52:12.140 --> 00:52:13.740
Light edges.

00:52:13.740 --> 00:52:15.810
This is what we call the
light depth of a node.

00:52:22.440 --> 00:52:29.545
This is the number of light
edges on a root to the path.

00:52:38.070 --> 00:52:42.374
And it is always,
at most, log n.

00:52:42.374 --> 00:52:44.040
Now, remember heavy
edges could be huge.

00:52:44.040 --> 00:52:46.380
Maybe you follow, maybe
your tree is a path.

00:52:46.380 --> 00:52:47.940
Then every edge is heavy.

00:52:47.940 --> 00:52:53.580
And you n of them to
get from the root of v.

00:52:53.580 --> 00:52:55.480
So we can't bound the
number of heavy edges.

00:52:55.480 --> 00:52:59.760
But the number of light
we can bound as log n.

00:52:59.760 --> 00:53:04.520
This is where heavy light
to composition is useful.

00:53:04.520 --> 00:53:06.324
So you've got preferred
path composition.

00:53:06.324 --> 00:53:08.490
Our Or data structure, we're
not going to change it.

00:53:08.490 --> 00:53:09.970
It's still following
the preferred path

00:53:09.970 --> 00:53:10.720
the decomposition.

00:53:10.720 --> 00:53:13.350
But our analysis is going
to think about which edges

00:53:13.350 --> 00:53:16.830
are heavy and which are light.

00:53:16.830 --> 00:53:20.310
In general, an edge can
have four different states.

00:53:20.310 --> 00:53:22.710
It can be preferred
or not preferred.

00:53:22.710 --> 00:53:25.110
And it can be preferred
or not preferred,

00:53:25.110 --> 00:53:27.020
it could be heavy or light.

00:53:27.020 --> 00:53:29.050
All four of those
combinations are possible,

00:53:29.050 --> 00:53:31.560
because one of them has to
do with the access sequence,

00:53:31.560 --> 00:53:34.026
the other has to do with
the structure of the tree.

00:53:34.026 --> 00:53:35.900
These are basically
orthogonal to each other.

00:53:38.588 --> 00:53:44.610
OK, so let's maybe go here.

00:54:09.990 --> 00:54:12.890
So next thing I'm going to do
is use heavy light decomposition

00:54:12.890 --> 00:54:16.250
to analyze total number of
preferred child changes,

00:54:16.250 --> 00:54:18.470
by looking at not only
whether an edge is preferred

00:54:18.470 --> 00:54:20.600
or not, but whether
it is heavy or light.

00:54:23.960 --> 00:54:32.775
We're going to get an order m
log n bound on preferred child

00:54:32.775 --> 00:54:33.275
changes.

00:54:40.970 --> 00:54:42.860
So here's the big idea.

00:55:29.970 --> 00:55:33.990
In order for a preferred
child to change,

00:55:33.990 --> 00:55:36.360
I mean when you change
for a child of one node

00:55:36.360 --> 00:55:39.870
from this to this, I'm
going to think of this edge

00:55:39.870 --> 00:55:42.270
as being destroyed
from its preferredness,

00:55:42.270 --> 00:55:46.520
and this one is being created
in it's preferredness.

00:55:46.520 --> 00:55:52.140
OK, so of course, if we could
count preferred edge equations,

00:55:52.140 --> 00:55:56.940
that would be basically the
same as preferred child changes.

00:55:56.940 --> 00:56:00.900
Or we could count preferred
edge destructions,

00:56:00.900 --> 00:56:04.030
that would be basically, the
same as the number of changes.

00:56:04.030 --> 00:56:05.610
OK, so that's the idea.

00:56:05.610 --> 00:56:08.220
If you ignore this part, or
look at pilferage equations

00:56:08.220 --> 00:56:09.480
or prefer it is destructions.

00:56:09.480 --> 00:56:11.370
But then I also care
about whether that edge

00:56:11.370 --> 00:56:13.890
is light or heavy.

00:56:13.890 --> 00:56:16.530
So it turns out for
the light edges,

00:56:16.530 --> 00:56:19.527
it's going to be easier to
talk about the creations

00:56:19.527 --> 00:56:20.610
or to bound the creations.

00:56:20.610 --> 00:56:22.310
For heavy edges is
going to be easier

00:56:22.310 --> 00:56:24.360
to bound the destructions.

00:56:24.360 --> 00:56:26.910
If I do both of those and
add them up, that in total

00:56:26.910 --> 00:56:30.330
is, basically, the number
of preferred edge changes

00:56:30.330 --> 00:56:32.460
according to whether
there is light or heavy.

00:56:32.460 --> 00:56:35.200
You need to add in a
little bit more because

00:56:35.200 --> 00:56:38.160
and edge might get created
but never destroyed.

00:56:38.160 --> 00:56:41.310
And if it's heavy, then
it won't get counted here.

00:56:41.310 --> 00:56:43.290
Or an edge might get
destroyed because it

00:56:43.290 --> 00:56:45.600
exists originally,
never got created

00:56:45.600 --> 00:56:47.309
but it got destroyed
over the operations.

00:56:47.309 --> 00:56:49.558
And if it was light, then
it wouldn't be counted here.

00:56:49.558 --> 00:56:51.480
So just add on n plus
1 for all the edges

00:56:51.480 --> 00:56:53.100
might get a bonus point.

00:56:53.100 --> 00:56:56.260
But, otherwise,
this will bound it,

00:56:56.260 --> 00:56:58.345
it's going to look at
light edge creations--

00:56:58.345 --> 00:57:01.800
creations, light preferred edge
creations, heavy preferred edge

00:57:01.800 --> 00:57:02.954
distructions.

00:57:02.954 --> 00:57:05.370
And it can be destroyed because
it becomes no longer heavy

00:57:05.370 --> 00:57:06.990
or no longer preferred.

00:57:06.990 --> 00:57:09.600
And it can be created
because it becomes light

00:57:09.600 --> 00:57:12.810
or it becomes preferred and
was already the other one.

00:57:12.810 --> 00:57:14.310
OK, so all we need
to do is think

00:57:14.310 --> 00:57:18.510
about, in all these operations,
access link-cut, just

00:57:18.510 --> 00:57:19.230
the updates.

00:57:19.230 --> 00:57:21.720
So access link/cut.

00:57:21.720 --> 00:57:23.850
How can this change?

00:57:23.850 --> 00:57:24.975
So let's start with access.

00:57:30.180 --> 00:57:33.060
So access.

00:57:33.060 --> 00:57:33.690
The hard one.

00:57:37.620 --> 00:57:39.820
Well, there's all
this implementation,

00:57:39.820 --> 00:57:41.730
which is dealing with
the tree of ox trees,

00:57:41.730 --> 00:57:44.100
but really, an access
does a very simple thing.

00:57:44.100 --> 00:57:47.460
It makes the path from
the root to be preferred.

00:57:47.460 --> 00:57:48.790
That's its goal.

00:57:48.790 --> 00:57:52.920
So there's the root, it's
to v, this becomes preferred

00:57:52.920 --> 00:57:54.630
whether it was before or not.

00:57:54.630 --> 00:57:57.300
Some of it was before
some of it wasn't.

00:57:57.300 --> 00:58:00.702
So some of these might
be on newly preferred.

00:58:05.630 --> 00:58:07.820
It does not change which
edges are heavy or light.

00:58:07.820 --> 00:58:09.350
It does not change the
structure of the tree

00:58:09.350 --> 00:58:10.266
when you do an access.

00:58:10.266 --> 00:58:12.740
Only link/cut changed the
structure of the tree.

00:58:12.740 --> 00:58:16.010
So it makes some of
these edges preferred.

00:58:16.010 --> 00:58:19.070
What that means, of course,
is that some other edges

00:58:19.070 --> 00:58:21.770
used to be preferred and
are no longer preferred.

00:58:21.770 --> 00:58:24.510
Those are the preferred
child changes.

00:58:24.510 --> 00:58:27.140
So if we look at
this, first concern

00:58:27.140 --> 00:58:29.620
is that we're creating
new preferred edges,

00:58:29.620 --> 00:58:33.074
so maybe we create some
new light preferred edges.

00:58:33.074 --> 00:58:34.490
How many new light
preferred edges

00:58:34.490 --> 00:58:38.250
could we create along this path?

00:58:38.250 --> 00:58:39.110
Most log n.

00:58:39.110 --> 00:58:43.380
Whatever the light depth
of v is as an upper bound.

00:58:43.380 --> 00:58:52.490
So make, at most, log
and, like preferred edges,

00:58:52.490 --> 00:58:56.420
because they all live
on a single path.

00:58:56.420 --> 00:58:58.430
And it would be really
hard to bound how many

00:58:58.430 --> 00:59:01.050
heavy preferred edges we make.

00:59:01.050 --> 00:59:02.050
But we don't have to.

00:59:02.050 --> 00:59:04.460
We don't have to worry about
heavy preferred edges being

00:59:04.460 --> 00:59:05.510
destroyed.

00:59:05.510 --> 00:59:07.310
Now, those edges
could be these ones.

00:59:07.310 --> 00:59:09.740
These edges used to be
preferred, now they're not.

00:59:09.740 --> 00:59:13.610
If they were heavy, then
I have to pay for them.

00:59:13.610 --> 00:59:17.420
But the number of these
edges is equal to,

00:59:17.420 --> 00:59:19.310
or is at most, the
number of these edges.

00:59:19.310 --> 00:59:21.890
I mean, if this edge
was heavy, every node

00:59:21.890 --> 00:59:23.960
has only one heavy down pointer.

00:59:23.960 --> 00:59:27.280
So if this edge is heavy hanging
off, then this one is light.

00:59:27.280 --> 00:59:29.880
We know there's only
log n light edges here.

00:59:29.880 --> 00:59:31.520
So the number of
heavy edges coming off

00:59:31.520 --> 00:59:35.370
here can also be most log n,

00:59:35.370 --> 00:59:43.740
So destroy, at most, log
n heavy preferred edges.

00:59:47.120 --> 00:59:51.800
Yeah In some sense,
we don't even really

00:59:51.800 --> 00:59:55.040
are about the word
preferred here.

00:59:55.040 --> 00:59:57.900
But, of course, we're not
making them, light so anyway.

01:00:01.324 --> 01:00:02.212
Is that clear?

01:00:02.212 --> 01:00:04.670
Now, there's actually one more
edge that could change which

01:00:04.670 --> 01:00:07.880
is, there used to be a preferred
edge from v, now there isn't.

01:00:07.880 --> 01:00:11.220
We destroyed that in the very
beginning of the operation.

01:00:11.220 --> 01:00:15.650
So maybe plus 1 that might have
destroyed one more heavy edge.

01:00:15.650 --> 01:00:19.940
But overall order log n.

01:00:19.940 --> 01:00:22.745
So, actually, really
easy to analyze access.

01:00:26.100 --> 01:00:27.210
Any questions about that?

01:00:42.500 --> 01:00:50.000
OK, link/cut not
much to say here.

01:00:50.000 --> 01:00:53.600
Yeah, so link/cut don't really
change what's preferred.

01:00:53.600 --> 01:00:56.570
I'm analyzing-- I'm going
to think about what link

01:00:56.570 --> 01:00:58.310
does after it accesses v and w.

01:00:58.310 --> 01:01:00.710
Because access we've
already analyzed.

01:01:00.710 --> 01:01:04.730
So link is just
these two operations

01:01:04.730 --> 01:01:06.540
which add a single pointer.

01:01:06.540 --> 01:01:10.760
So if you look at what that's
doing in the represented tree,

01:01:10.760 --> 01:01:14.330
which was v was the
route and we made

01:01:14.330 --> 01:01:22.490
it to be a new child w, which
lived in some tree over here.

01:01:22.490 --> 01:01:24.365
That's in the represented
tree, what happens.

01:01:28.470 --> 01:01:34.100
What happens is
that w gets heavier.

01:01:34.100 --> 01:01:36.680
I guess also this get's heavier.

01:01:36.680 --> 01:01:41.180
All the nodes on this route
to w path get heavier.

01:01:41.180 --> 01:01:44.270
That's all that happens
in terms of heavy, light.

01:01:44.270 --> 01:01:45.890
Preferred paths don't change.

01:01:45.890 --> 01:01:49.870
It's just about heavy
and light changing.

01:01:49.870 --> 01:01:52.850
OK, in fact, this will
be a preferred path

01:01:52.850 --> 01:01:56.060
from the root to v because
we just accessed those guys.

01:02:02.640 --> 01:02:06.670
So we're heavying edges,
which means you might create

01:02:06.670 --> 01:02:09.010
new heavy preferred edges.

01:02:09.010 --> 01:02:12.760
But we don't care about heavy
preferred edges being created.

01:02:12.760 --> 01:02:16.580
We only care about
them being destroyed.

01:02:16.580 --> 01:02:18.010
So has anything changed?

01:02:18.010 --> 01:02:22.232
Well, there might have been a
heavy edge hanging off of here.

01:02:22.232 --> 01:02:22.940
Is that possible?

01:02:26.550 --> 01:02:29.640
Yeah, so this might turn
light, because this one

01:02:29.640 --> 01:02:31.340
became heavier.

01:02:31.340 --> 01:02:33.090
So this edge might
become light, which

01:02:33.090 --> 01:02:36.180
means we might have
potentially lost--

01:02:36.180 --> 01:02:38.430
this could have been
preferred before.

01:02:38.430 --> 01:02:40.722
It wasn't preferred,
so who cares?

01:02:40.722 --> 01:02:42.180
If we've already
done the accesses,

01:02:42.180 --> 01:02:43.830
the edges are already
not preferred.

01:02:43.830 --> 01:02:45.032
So not a big deal.

01:02:45.032 --> 01:02:45.990
So can anything happen?

01:02:45.990 --> 01:02:48.839
I think not.

01:02:48.839 --> 01:02:50.880
Some of the edges on the
path might become heavy,

01:02:50.880 --> 01:02:53.160
but we don't care because
they are preferred.

01:02:53.160 --> 01:02:55.260
Some of the edges off the
path might become light,

01:02:55.260 --> 01:02:57.260
but we don't care because
they're not preferred.

01:02:57.260 --> 01:02:58.680
Done.

01:02:58.680 --> 01:03:04.610
So this actually costs zero
in just analyzing number

01:03:04.610 --> 01:03:05.860
of preferred child changes.

01:03:05.860 --> 01:03:09.210
Cuts, not quite so simple.

01:03:09.210 --> 01:03:13.450
When we do a cut,
we're lightning stuff.

01:03:16.530 --> 01:03:19.550
The path from the root to
v in the represented tree,

01:03:19.550 --> 01:03:23.580
when we line up there,
becomes lighter,

01:03:23.580 --> 01:03:28.290
because we cut off that
whole subtree containing v.

01:03:28.290 --> 01:03:33.210
So we might create light
preferred edges on that path.

01:03:33.210 --> 01:03:35.470
And that's something we
actually want to count.

01:03:35.470 --> 01:03:37.710
we count number of light
preferred edges created.

01:03:37.710 --> 01:03:43.294
But, again, they're on a
path so it's, at most, log n

01:03:43.294 --> 01:03:50.560
Most log n light
preferred edges created.

01:03:50.560 --> 01:03:52.560
We don't care about edges
hanging off that path

01:03:52.560 --> 01:03:54.143
because they're not
preferred anymore,

01:03:54.143 --> 01:03:57.299
so it's nothing to talk about.

01:03:57.299 --> 01:03:57.840
So that's it.

01:03:57.840 --> 01:04:01.701
That proves m log n
preferred child changes.

01:04:01.701 --> 01:04:04.200
It's amortized because we're
doing this creation/destruction

01:04:04.200 --> 01:04:05.370
business.

01:04:05.370 --> 01:04:08.720
This thing is worst case log n
per operation, this quantity.

01:04:08.720 --> 01:04:10.890
But when you sum it
up, then you actually

01:04:10.890 --> 01:04:12.880
get about the number of
preferred child changes

01:04:12.880 --> 01:04:13.380
overall.

01:04:19.800 --> 01:04:22.770
So if you plug that
into this bound,

01:04:22.770 --> 01:04:25.020
we get a log squared m bound.

01:04:25.020 --> 01:04:28.450
Big deal.

01:04:28.450 --> 01:04:30.030
But with a little
bit more work, we

01:04:30.030 --> 01:04:31.920
can actually get a log n bound.

01:04:39.840 --> 01:04:41.280
For this, we need
to actually know

01:04:41.280 --> 01:04:43.880
a little bit about
splay tree analysis.

01:04:43.880 --> 01:04:46.436
I didn't cover in Lecture Six.

01:04:46.436 --> 01:04:48.560
You probably would have
forgotten it by now anyway.

01:04:48.560 --> 01:04:50.880
So let me give you
what little you need

01:04:50.880 --> 01:04:54.180
to know about splay analysis.

01:04:54.180 --> 01:04:57.930
First, I need to define a
slightly weird quantity.

01:04:57.930 --> 01:05:00.600
It's kind of like
the weight of a node.

01:05:00.600 --> 01:05:04.770
It's a capital W, but
a little bit weird.

01:05:20.600 --> 01:05:23.640
OK, now we're thinking
about the tree of ox trees.

01:05:23.640 --> 01:05:25.540
For the analysis we need that.

01:05:25.540 --> 01:05:27.292
It's a tree of splay trees.

01:05:27.292 --> 01:05:29.500
And what I'm looking at, is
in that tree of ox trees,

01:05:29.500 --> 01:05:31.774
how many nodes are
in the subtree of v?

01:05:31.774 --> 01:05:33.190
That's what I'm
going to call wv .

01:05:33.190 --> 01:05:36.760
Whereas size of v was thinking
in the represented tree.

01:05:36.760 --> 01:05:38.590
So this is a totally
different world.

01:05:38.590 --> 01:05:41.050
Here, we're thinking about
the tree of ox trees.

01:05:41.050 --> 01:05:44.640
So one way you can
rewrite this count

01:05:44.640 --> 01:05:54.490
as the sum of all nodes w in
the ox tree containing v. It's

01:05:54.490 --> 01:05:57.130
a weird notation, but look at
all the other nodes in the ox

01:05:57.130 --> 01:05:59.417
tree--

01:05:59.417 --> 01:06:00.000
is that right?

01:06:00.000 --> 01:06:02.642
Sorry.

01:06:02.642 --> 01:06:03.142
No.

01:06:06.960 --> 01:06:19.140
I should say w in v's
subtree in v's ox tree.

01:06:19.140 --> 01:06:20.610
It's awkward to say.

01:06:20.610 --> 01:06:24.930
What I mean is there is an
ox tree containing a node v,

01:06:24.930 --> 01:06:28.650
and I want to look in that
subtree I'll know as w.

01:06:28.650 --> 01:06:31.170
Just within the ox tree though.

01:06:31.170 --> 01:06:35.700
And for all those nodes,
I take 1 plus the size

01:06:35.700 --> 01:06:38.573
of ox trees hanging off.

01:06:46.970 --> 01:06:48.770
So total number of nodes.

01:06:48.770 --> 01:06:52.190
And when I say
hanging off I mean

01:06:52.190 --> 01:06:54.930
via pathed parent pointers.

01:06:54.930 --> 01:06:58.070
So down here, there are
trees, add up all their sizes

01:06:58.070 --> 01:07:01.820
total number of nodes in
them, add one for w itself,

01:07:01.820 --> 01:07:04.340
that's another way
of writing this.

01:07:04.340 --> 01:07:10.910
I'll just mention that this
part is what's normally

01:07:10.910 --> 01:07:12.530
considered in splay trees.

01:07:12.530 --> 01:07:15.230
This is a bonus thing that,
basically, doesn't matter.

01:07:17.940 --> 01:07:20.400
I'll justify that in a second.

01:07:20.400 --> 01:07:21.980
So we define a
potential function

01:07:21.980 --> 01:07:29.420
for our amortization fee, which
is sum over all nodes v of log

01:07:29.420 --> 01:07:33.500
this quantity wv, this thing.

01:07:33.500 --> 01:07:37.460
So just think of this
as an abstract quantity,

01:07:37.460 --> 01:07:41.040
which for every node it has
some number associated with it.

01:07:41.040 --> 01:07:45.200
Splay trees allow you to assign
arbitrary weight to every node,

01:07:45.200 --> 01:07:48.350
use this potential function,
and prove abound --which

01:07:48.350 --> 01:07:57.700
is called the access lemma
The access lemma says is that,

01:07:57.700 --> 01:08:01.090
for this potential
function, the amortized cost

01:08:01.090 --> 01:08:12.620
of doing a splay
operation splay of v,

01:08:12.620 --> 01:08:30.290
is, at most, three times
log w of root of v's ox tree

01:08:30.290 --> 01:08:38.029
minus log w of v plus 1.

01:08:41.000 --> 01:08:43.969
OK, so this is something
called the access Lemma

01:08:43.969 --> 01:08:46.310
It's used to prove, for
example, that splay trees have

01:08:46.310 --> 01:08:48.145
log n performance amortize.

01:08:48.145 --> 01:08:49.520
It's also used to
prove that they

01:08:49.520 --> 01:08:52.040
have a working set
bound, which you

01:08:52.040 --> 01:08:54.229
may recall from Lecture Six.

01:08:54.229 --> 01:08:57.040
But we never actually mentioned
the access lemma It's a tool.

01:08:57.040 --> 01:08:57.979
It's an analysis tool.

01:09:00.950 --> 01:09:04.266
This works no matter
how the w's are defined.

01:09:04.266 --> 01:09:06.140
And remember, we're
thinking of splaying just

01:09:06.140 --> 01:09:07.529
within a single ox tree.

01:09:07.529 --> 01:09:10.069
So the size of the
ox trees hanging off

01:09:10.069 --> 01:09:11.460
don't change during a splay.

01:09:11.460 --> 01:09:13.500
They just come
along for the ride.

01:09:13.500 --> 01:09:16.712
So the old analysis
of splay trees

01:09:16.712 --> 01:09:18.170
I haven't proved
this lemma to you.

01:09:18.170 --> 01:09:21.710
But it still applies
in this setting.

01:09:21.710 --> 01:09:23.100
And given my lack of time.

01:09:23.100 --> 01:09:25.880
I will just say in
words, the way you prove

01:09:25.880 --> 01:09:27.800
this lemma is very simple.

01:09:27.800 --> 01:09:30.229
You do you analyze each
operation of display

01:09:30.229 --> 01:09:34.130
separately there's a zig-zag
case in a zigzag case.

01:09:34.130 --> 01:09:39.500
And you argue that every time
you do such an operation,

01:09:39.500 --> 01:09:44.240
you pay three times
a log of w of v

01:09:44.240 --> 01:09:48.740
after the operation minus log
of wv before the operation.

01:09:48.740 --> 01:09:51.680
So you just see how wv
changes when it goes up

01:09:51.680 --> 01:09:55.155
after you do display
operation, and turns out it's

01:09:55.155 --> 01:09:56.530
the most three
times log of that.

01:09:56.530 --> 01:09:58.290
And it has to do with
concavity of log n.

01:09:58.290 --> 01:10:00.650
It's just basic checking.

01:10:00.650 --> 01:10:03.500
Once you have that you
get a telescoping sum.

01:10:03.500 --> 01:10:07.820
Each operation is log
w new minus long w old.

01:10:07.820 --> 01:10:13.070
Those cancel, in turn, until
you get the final log w of v,

01:10:13.070 --> 01:10:17.720
minus the original log w of v.
The final log w is whatever--

01:10:17.720 --> 01:10:21.510
I mean, v becomes the root and
so it has everybody below it.

01:10:21.510 --> 01:10:24.440
So that's the axis lemma.

01:10:24.440 --> 01:10:28.010
So assuming the
access lemma, I want

01:10:28.010 --> 01:10:31.480
to prove to you a log n bound.

01:10:31.480 --> 01:10:53.920
Maybe over here OK,
another thing to note,

01:10:53.920 --> 01:10:57.430
when we change preferred
children, it does not affect w.

01:10:57.430 --> 01:11:01.880
W defined on the
tree of ox trees.

01:11:01.880 --> 01:11:03.800
If you turn a path
parent pointer

01:11:03.800 --> 01:11:06.975
into a regular parent pointer
or vice versa, It doesn't care.

01:11:06.975 --> 01:11:09.350
It looks the same from the
tree of ox trees' perspective.

01:11:09.350 --> 01:11:12.609
All that changes, all that
matters is when you do splays

01:11:12.609 --> 01:11:13.400
this stuff happens.

01:11:13.400 --> 01:11:15.710
But the splay analysis
tells us how splays behave.

01:11:15.710 --> 01:11:18.890
So we're kind of good.

01:11:18.890 --> 01:11:25.040
If you look at what we did
over here, when we splayed v,

01:11:25.040 --> 01:11:30.140
then we splayed w, then we did
a little bit of manipulation

01:11:30.140 --> 01:11:32.820
which doesn't matter
in this analysis.

01:11:32.820 --> 01:11:36.040
And then we splayed
v one more time.

01:11:36.040 --> 01:11:38.780
How much does that cost
according to the access lemma.

01:11:38.780 --> 01:11:43.220
It's basically going
to cost you order log

01:11:43.220 --> 01:11:51.620
w of little w minus
log w of v plus 1,

01:11:51.620 --> 01:12:00.410
because well is it clear?

01:12:00.410 --> 01:12:03.830
When we do the first splay
of v going up to the root

01:12:03.830 --> 01:12:07.460
that cost log of w of
the whole tree containing

01:12:07.460 --> 01:12:10.070
b minus longer wv.

01:12:10.070 --> 01:12:12.020
But if you just
look at log, I mean,

01:12:12.020 --> 01:12:16.580
w is higher than the root of
v. So if we take a log of w

01:12:16.580 --> 01:12:23.120
this the whole thing from w
downwards minus log wv, that

01:12:23.120 --> 01:12:27.170
includes the cost that we did
for the initial splay of v.

01:12:27.170 --> 01:12:30.530
Then when we played w, well
that's basically the same thing

01:12:30.530 --> 01:12:32.090
but the next level up.

01:12:32.090 --> 01:12:38.117
So if you look at log of w
minus log of w of next level up,

01:12:38.117 --> 01:12:39.950
that's what it's going
to cost this splay w.

01:12:39.950 --> 01:12:42.950
To splay v again, will
again cost this bound.

01:12:42.950 --> 01:12:48.620
The point is, we sum this up
over all the preferred child

01:12:48.620 --> 01:12:49.670
changes.

01:12:49.670 --> 01:12:53.720
And what we get is a
telescoping scum again.

01:12:53.720 --> 01:12:55.820
Same as in the display analysis.

01:12:55.820 --> 01:13:03.290
So we end up with order log w
of everything, which an n minus,

01:13:03.290 --> 01:13:05.480
I guess, the log of
w of the original v,

01:13:05.480 --> 01:13:07.220
-but we don't really
care about that--

01:13:07.220 --> 01:13:10.355
plus the number of
preferred child changes.

01:13:14.950 --> 01:13:18.230
And now we're golden because
before, the obvious bound was

01:13:18.230 --> 01:13:21.249
number preferred child
changes times again, now

01:13:21.249 --> 01:13:22.790
it's number of
preferred time changes

01:13:22.790 --> 01:13:25.790
plus log n for an entire access.

01:13:25.790 --> 01:13:27.830
And so we pay log n here.

01:13:27.830 --> 01:13:30.370
We already know the amortize
number preferred child changes

01:13:30.370 --> 01:13:32.060
is log n per operation.

01:13:32.060 --> 01:13:35.930
So overall the amortize
cost per operation is log n.

01:13:35.930 --> 01:13:39.020
And we're done.

01:13:39.020 --> 01:13:43.370
So I'll just mention the worst
case version of link-cut trees

01:13:43.370 --> 01:13:47.060
instead of the amortize
splay based version.

01:13:47.060 --> 01:13:49.710
They actually store the
heavy light decomposition.

01:13:49.710 --> 01:13:52.430
They don't use preferred path
to decomposition at all, which

01:13:52.430 --> 01:13:54.941
makes all the algorithms messy.

01:13:54.941 --> 01:13:57.440
But you can just maintain the
heavy [? likely ?] composition

01:13:57.440 --> 01:14:00.860
position dynamically as
the tree is changing,

01:14:00.860 --> 01:14:04.610
and then you use a kind
of weight balanced trees,

01:14:04.610 --> 01:14:09.470
like we saw in the
strings lecture, where

01:14:09.470 --> 01:14:13.560
the depth of a node is sort
of related to log of its size

01:14:13.560 --> 01:14:14.910
or inversely related I guess.

01:14:14.910 --> 01:14:18.410
So you try to put all the
heavy things near the root,

01:14:18.410 --> 01:14:20.450
because they're more
likely to be accessed.

01:14:20.450 --> 01:14:22.940
And then you guarantee that
the overall tree of ox trees

01:14:22.940 --> 01:14:27.500
has long n depth by skewing
each of the end of the ox trees

01:14:27.500 --> 01:14:29.822
to match.

01:14:29.822 --> 01:14:32.030
So it can be done but all
the operations are messier,

01:14:32.030 --> 01:14:34.571
because you no longer have the
convenience of preferred paths

01:14:34.571 --> 01:14:37.420
to make it easy to
link/cut things.