RetroactiveDataStructures
RetroactiveDataStructures
ERIK D. DEMAINE
Massachusetts Institute of Technology
JOHN IACONO
Polytechnic University
AND
STEFAN LANGERMAN
Université Libre de Bruxelles
Abstract. We introduce a new data structuring paradigm in which operations can be performed on a
data structure not only in the present, but also in the past. In this new paradigm, called retroactive
data structures, the historical sequence of operations performed on the data structure is not fixed.
The data structure allows arbitrary insertion and deletion of operations at arbitrary times, subject only
to consistency requirements. We initiate the study of retroactive data structures by formally defining
the model and its variants. We prove that, unlike persistence, efficient retroactivity is not always
achievable. Thus, we present efficient retroactive data structures for queues, doubly ended queues,
priority queues, union-find, and decomposable search structures.
Categories and Subject Descriptors: E.1 [Data]: Data Structures; F.2.2 [Analysis of Algorithms and
Problem Complexity]: Nonnumerical Algorithms and Problems
General Terms: Algorithms, Theory, Design, Performance
Additional Key Words and Phrases: History, time travel, rollback, persistence, point location
ACM Reference Format:
Demaine, E. D., Iacono, J., and Langerman, S. 2007. Retroactive data structures. ACM Trans.
Algor. 3, 2, Article 13 (May 2007), 20 pages. DOI = 10.1145/ 1240233.1240236 http://doi.acm.
org/10.1145/1240233.1240236
A preliminary version of this article appeared in the 2004 Proceedings of the 15th Annual ACM-SIAM
Symposium on Discrete Algorithms (SODA), pp. 274–283. The work of the first and second authors
was supported in part by National Science Foundation Grants OISE-0334653 and CCF-0430849. The
third author is Chercheur Qualifié du FNRS.
Authors’ Addresses: E. D. Demaine, MIT Computer Science and Artificial Intelligence Labora-
tory, 32 Vassar Street, Cambridge, MA 02139, e-mail: [email protected]; J. Iacono, Polytechnic
University, 5 MetroTech Center, Brooklyn, NY 11201; http://john.poly.edu; S. Langerman,
Université Libre de Bruxelles, Département d’informatique, ULB CP212, Belgium, e-mail:
[email protected].
Permission to make digital or hard copies of part or all of this work for personal or classroom use is
granted without fee provided that copies are not made or distributed for profit or direct commercial
advantage and that copies show this notice on the first page or initial screen of a display along with the
full citation. Copyrights for components of this work owned by others than ACM must be honored.
Abstracting with credit is permitted. To copy otherwise, to republish, to post on servers, to redistribute
to lists, or to use any component of this work in other works requires prior specific permission and/or
a fee. Permissions may be requested from Publications Dept., ACM, Inc., 2 Penn Plaza, Suite 701,
New York, NY 10121-0701 USA, fax +1 (212) 869-0481, or [email protected].
C 2007 ACM 1549-6325/2007/05-ART13 $5.00 DOI 10.1145/1240233.1240236 http://doi.acm.org/
10.1145/1240233.1240236
ACM Transactions on Algorithms, Vol. 3, No. 2, Article 13, Publication date: May 2007.
2 E. D. DEMAINE ET AL.
1. Introduction
Suppose that we just discovered that an operation previously performed in a database
was erroneous (e.g., from a human mistake), and we need to change the operation.
In most existing systems, the only method to support these changes is to rollback
the state of the system to before the time in question and then reexecute all of the
operations from the modifications to the present. Such processing is wasteful, inef-
ficient, and often unnecessary. In this article we introduce and develop the notion of
retroactive data structures, which are data structures that efficiently support modi-
fications to the historical sequence of operations performed on the structure. Such
modifications could take the form of retroactively inserting, deleting, or changing
one of the operations performed at a given time in the past on the data structure in
question.
After defining the model, we show that there is no general efficient transfor-
mation from nonretroactive structures into retroactive structures. We then turn
to the development of specific retroactive structures. For some classes of data
structures (commutative and invertible data structures, and data structures for de-
composable search problems), we present general transformations to make data
structures efficiently retroactive. For other data structures where the dependency
between operations is stronger, efficient retroactivity requires the development of
new techniques. In particular, we present a retroactive heap that achieves optimal
bounds.
ACM Transactions on Algorithms, Vol. 3, No. 2, Article 13, Publication date: May 2007.
Retroactive Data Structures 3
radically affect the contents of all later versions. In effect, we sever the relationship
between time as perceived by a data structure, and time as perceived by the user of
a data structure. Operations such as “Insert 42” now become “Insert at time 10 the
operation ‘Insert 42’ ”.
ACM Transactions on Algorithms, Vol. 3, No. 2, Article 13, Publication date: May 2007.
4 E. D. DEMAINE ET AL.
again, and the late fee is removed as per the previous agreement. The next month,
interest from the (now removed) late fee appears on the bill. Once again you must
call customer service to fix the problem. This sequence of events is typical and
results from the system’s inability to retroactively change the destination of the
payment.
Intentional Manipulation of the Past. In Orwell’s 1984 [1949], the protagonist’s
job was to change past editions of a newspaper to enable the government to effec-
tively control the past. “A number of the Times which might, because of changes
in political alignment, or mistaken prophecies uttered by Big Brother, have been
rewritten a dozen times still stood on the files bearing its original data, and no other
copy existed to contradict it.” [Orwell 1949, p. 37]
While we may consider this to be inappropriate behavior for a government,
in many corporate settings, such behavior is commonplace. If the actions of an
executive of the corporation are bringing negative publicity to a company, it may
be desirable to not only remove the executive from the company, but to purge the
companies past and present literature of references to this person, while maintaining
consistency amongst documents.
Version Control. Software such as Microsoft Word and CVS allow maintenance
of a version tree of documents. The software allows the user to look at historical
versions and to create new versions from them. When a mistake is discovered,
it is possible to rollback the documents involved to a previous version, and start
again from this version. However, in some situations, it would be useful if we could
change a previous version and then propagate these changes into future versions. For
example, suppose that there are many versions of documentation corresponding to
the many versions of a product, and all of these versions are available online for users
of the various versions. If an error is found in the documentation, we would like to be
able to change the error in the version where it was introduced, and have the change
automatically propagate into all of the documents containing the error (though
perhaps some later versions changed the erroneous text for other reasons, and thus
need not be changed). Although such changes could be propagated by brute-force
methods, a retroactive approach would be able to quickly make such changes,
thus leading to a new generation of generalized document life-cycle management
tools.
Dynamization. Some static algorithms or data structures are constructed by per-
forming on some dynamic data structure a sequence of operations determined
by the input. For example, building the point-location data structure of Sarnak
and Tarjan [1986] consists of performing a sequence of insertions and deletions
on a persistent search tree. Specifically, the evolution of the search tree tracks
the intersection of the input with a vertical line that sweeps continuously from
left-to-right; thus, queries at a particular time in the persistent structure corre-
spond to queries at a particular horizontal coordinate. If we used full retroac-
tivity instead of persistence, we would have the ability to make changes to the
search tree at arbitrary times, which corresponds to dynamically changing the
input that defined the sequence of operations performed on the data structure.
The best data structure for dynamic planar point location uses O(log n log log n)
amortized time per query. Achieving dynamic planar point location in O(log n)
time per operation reduces to a problem in retroactive data structures, though
ACM Transactions on Algorithms, Vol. 3, No. 2, Article 13, Publication date: May 2007.
Retroactive Data Structures 5
FIG. 1. A single insertion of an operation in a retroactive heap data structure (here, retroactively
inserting “insert(0)” at time t = 0) can change the outcome of every delete-min operation and the
lifespan of every element.
this problem is, so far, unsolved.1 More generally, retroactive data structures
can help dynamize static algorithms or data structures that use dynamic data
structures.
1.3. TIME IS NOT AN ORDINARY DIMENSION. One may think that the problem
of retroactive data structures can be solved by adding one more dimension to the
structure under consideration. For example, in the case of a min-heap, it would seem
at first glance that we could create a two-dimensional variant of a heap, and the
problem would be solved. The idea is to assign the key values of items in the heap
to the y axis and use the x axis to represent time. In this representation, each item
in the heap is represented by a horizontal line segment. The left endpoint of this
segment represents the time at which an item is inserted into the heap and the right
endpoint represents when the item is removed. If the only operations supported by
the heap are insert() and delete-min(), then we have the additional property that
there are no points below the right endpoint of any segment because only minimal
items are removed from the heap. While this seems to be a clean two-dimensional
representation of a heap throughout time, retroactively adding and removing an
operation in the heap cannot simply be implemented by adding or removing a line
segment. In fact, the endpoints of all the segments could be changed by inserting a
single operation, as illustrated in Figure 1.
1
This problem is indeed our original motivation for introducing the notion of retroactive data
structures. It is probably the same motivation that led Driscoll et al. [1989] to pose their open problem:
“Find a way to allow update operations that change many versions simultaneously.” The particular
case of modifying the versions corresponding to an interval of time (posed explicitly as well) is
equivalent to retroactivity if the operations have inverses (see Section 4). A similar idea is suggested
explicitly in Snoeyink’s survey on point location [1997, p. 566], where he asks “can persistent data
structures be made dynamic?”
ACM Transactions on Algorithms, Vol. 3, No. 2, Article 13, Publication date: May 2007.
6 E. D. DEMAINE ET AL.
Thus, while time can be drawn as a spatial dimension, this dimension is special
in that complicated dependencies may exist so that when small changes are made to
some part of the diagram, changes may have to be made to the rest of the diagram.
Thus, traditional geometric and high-dimensional data structures cannot be used
directly to solve most retroactive data-structure problems. New techniques must
be introduced to create retroactive data structures, without explicitly storing every
state of the structure.
1.4. OUTLINE. The rest of the article proceeds as follows. In Section 2, we fur-
ther develop the model of retroactive data structures and explore possible variants
on the model. Next, Section 3 considers some basic problems about retroactivity,
proving separations among the model variations and proving that automatic effi-
cient retroactivity is impossible in general. In Section 4, we present two general
transformations to construct an efficient retroactive version of a data structure, one
for commutative invertible operations and one for any decomposable search prob-
lem. Finally, in Section 5, we discuss specific data structures for which we propose
to create efficient retroactive structures. Table I in Section 5 gives a partial summary
of the results obtained.
2. Definitions
In this section, we define the precise operations that we generally desire from a
retroactive data structure.
2.1. PARTIAL RETROACTIVITY. Any data structural problem can be reformu-
lated in the retroactive setting. In general, the data structure involves a sequence
of updates and queries made over time. We define the list U = [u t1 , . . . , u tm ] of
updates performed on the data structure, where u ti is the operation performed at
time ti , and t1 < t2 < · · · < tm . (We assume that there is at most one operation
performed at any given time).
The data structure is partially retroactive if, in addition to supporting updates
and queries on the “current state” of the data structure (present time), it supports
insertion and deletion of updates at past times, as well. In other words, there are
two operations of interest:
(1) Insert(t, u): Insert into U a new update operation u at time t (assuming that no
operation already exists at time t).
(2) Delete(t): Delete the past update operation u t from the sequence U of updates
(assuming such an operation exists).
Thus, the retroactive versions of standard insert(x) and delete(x) operations are
Insert(t, “insert(x)”), Insert(t, “delete(x)”), and Delete(t), where t represents a
moment in time. For example, if ti−1 < t < ti , Insert(t, “insert(x)”) creates a
new operation u = insert(x), which inserts a specified element x, and modifies
history to suppose that operation u occurred between operations u ti−1 and u ti in the
past. Informally, we are traveling back in time to a prior state of the data structure,
introducing or preventing an update at that time, and then returning to the present
time.
All such retroactive changes on the operational history of the data structure po-
tentially affect all existing operations between the time of modification and the
ACM Transactions on Algorithms, Vol. 3, No. 2, Article 13, Publication date: May 2007.
Retroactive Data Structures 7
present time. Particularly interesting is the (common) case in which local changes
propagate in effect to produce radically different perceived states of the data struc-
ture. The challenge is to realize these perceived differences extremely efficiently
by implicit representations.
2.2. FULL RETROACTIVITY. The definitions just presented capture only a partial
notion of retroactivity: the ability to insert or delete update operations in the past,
and to view the effects at the present time. Informally, we can travel back in time
to modify the past, but we cannot directly observe the past. A data structure is fully
retroactive if, in addition to allowing updates in the past, it can answer queries about
the past. In some sense, this can be seen as making a partially retroactive version of a
persistent version of the original structure. Thus, the standard search(x) operation,
which finds an element x in the data structure, becomes Query(t, “search(x)”),
which finds the element x in the state of the data structure at time t.
2.3. RUNNING TIMES. When expressing the running times of retroactive data
structures, we will use m for the total number of updates performed in the structure
(retroactive or not), r for the number of updates before which the retroactive oper-
ation is to be performed (i.e., tm−r < t ≤ tm−r +1 ), and n for the maximum number
of elements present in the structure at any single time. Most running times in this
article are expressed in terms of m, but in many cases, it is possible to improve the
data structures to express the running time of operations in terms of n and r , so that
retroactive operations performed at a time closer to the present are executed faster.
2.4. CONSISTENCY. We assume that only valid retroactive operations are per-
formed. For example, in a retroactive dictionary, a delete(k) operation for a key k
must always appear after a corresponding insert(k) in the list U ; and in a retroactive
stack, the number of push() operations is always larger than that of pop() operations
for any prefix of U . The retroactive data structures we describe in this article will
not check the validity of retroactive updates, but it is often easy to create a data
structure so as to verify the validity of a retroactive operation.
3. General Theory
The goal of this research is to design retroactive structures for abstract data types
with performance similar to their nonretroactive counterparts. This section consid-
ers some of the most general problems concerning when this is possible.
Unless stated otherwise, our data structures use the RAM model of computation
(or Real RAM when real values are used), and sometimes work in the pointer-
machine model [Tarjan 1979] as well. Our lower bounds use the history-dependent
algebraic-computation-tree model [Frandsena et al. 2001] or the cell-probe model
[Yao 1981].
3.1. AUTOMATIC RETROACTIVITY. A natural question in this area is the follow-
ing: Is there a general technique for converting any data structure in, for example,
the pointer-machine model into an efficient partially retroactive data structure?
Such a general technique would nicely complement existing methods for making
data structures persistent [Driscoll et al. 1989; Fiat and Kaplan 2001]. As described
in the Introduction, retroactivity is fundamentally different from persistence, and
known techniques do not apply.
ACM Transactions on Algorithms, Vol. 3, No. 2, Article 13, Publication date: May 2007.
8 E. D. DEMAINE ET AL.
One simple approach to this general problem is the rollback method. Here we store
as auxiliary information all changes to the data structure made by each operation
such that every change could be reversed. (For example, to enable rollback of a
memory-write operation, we store the value that was previously at the address.)
For operations in the present, the data structure proceeds as normal, modulo some
extra logging. When the user requests a retroactive change at a past time t with
tm−r < t < tm−r +1 , the data structure rollsback all changes made by operations
u m , . . . , u m−r +1 , then applies the retroactive change as if it were the present, and
finally reperformances all operations u m−r +1 , . . . , u m . Notice that these reperfor-
mances may act differently from how the operations were performed before, de-
pending on the retroactive change. Because the changes made to the data structure
are bounded by the time taken by the operations, a straightforward analysis proves
the following theorem.
THEOREM 1. Given any RAM data structure that performs a collection of oper-
ations, each in T (n) worst-case time, there is a corresponding partially retroactive
data structure that supports the same operations in O(T (n)) time, and supports
retroactive versions of those operations in O(r T (n)) time.
The rollback method is widely used in database management systems (see, e.g.,
Ramakrishnan and Gehrke [2002]) and robust file systems for concurrency control
and crash recovery. It has also been studied in the data structures literature under the
name of unlimited undo or backtracking [Mannila and Ukkonen 1986; Westbrook
and Tarjan 1989].
Of course, this result, as well as its extension to operations with nonuniform
costs, is far too inefficient for applications where r can be n or even larger—the
total number m of operations performed on the data structure. A natural goal is to
reduce the dependence on r in the running time of retroactive operations. We show
that this is not possible in the history-dependent algebraic-computation-tree model
[Frandsena et al. 2001], a generalization of the algebraic-computation-tree model in
which nodes can branch based on any finite-arity arithmetic predicate and in which
the entire tree of an operation can depend on the branches in all previous operations.
As a result, all lower bounds in this model carry over to the real-RAM model,
straight-line-program model, and algebraic-computation-tree model, as well. The
result also applies to the integer-RAM model, which allows indirect addressing
into an array by computed values, and the generalized real-RAM model, which
allows any piecewise-continuous function as an atomic operation; see Frandsena
et al. [2001].
THEOREM 2. There exists a data structure in the straight-line-program model
that supports updates and queries in O(1) time per operation, but any partially
retroactive data structure for the same operations requires (r ) time for ei-
ther updates or queries, both worst case and amortized, in the history-dependent
algebraic-computation-tree model, integer-RAM model, and generalized real-RAM
model.
PROOF. The data structure maintains two values X and Y, initially 0, and sup-
ports the updates addX(c) and addY(c), which add the value c to the value X or Y,
respectively, and mulXY(), which multiplies Y by X and stores the resulting value
in Y. Queries return the value of Y.
ACM Transactions on Algorithms, Vol. 3, No. 2, Article 13, Publication date: May 2007.
Retroactive Data Structures 9
ACM Transactions on Algorithms, Vol. 3, No. 2, Article 13, Publication date: May 2007.
10 E. D. DEMAINE ET AL.
than full retroactivity. In other words, is it easier to answer queries only about the
present? We first give a partial answer.
THEOREM 4. In the cell-probe model, there exists a data structure supporting
partially retroactive updates in O(1) time, but fully retroactive queries of the past
require (log n) time.
PROOF. The data structure is for the following problem: Maintain a set of
numbers subject to the update insert(c) which adds a number c to the set, and the
query sum() which reports the sum of all of the numbers. For this problem, the
only retroactive update operations are Insert(t, “insert(c)”) and Delete(t), whose
effects on queries about the present are to add or subtract a number to the current
aggregate. Thus, a simple data structure solves partially retroactive updates in O(1)
time per operation. In contrast, to support queries at arbitrary times, we need both
to remember the order of update operations and to support arbitrary prefix sums.
Thus, we obtain a lower bound of (log n) in the cell-probe model by a reduction
from dynamic prefix sums [Pătrascu and Demaine 2004].
On the other hand, we can show that it is always possible, at some cost, to convert
a partially retroactive data structure into a fully retroactive one.
THEOREM 5. Any partially retroactive data structure in the pointer-machine
model with constant indegree, supporting T (m)-time retroactive updates and Q(m)-
time queries about the present,
√ can be transformed into a fully retroactive √ data
structure with amortized O( m T (m))-time retroactive updates and O( m T (m)+
Q(m))-time fully retroactive queries using O(mT (m)) space.
√ √
PROOF. We define m checkpoints t1 , . . . , t√m such that at most (3/2) m
√
operations have occurred between consecutive checkpoints, and maintain m ver-
sions of the partially retroactive data structure D1 , . . . , D√m , where the structure
Di only contains updates that occurred before time ti . We also store the entire se-
quence of updates. When a retroactive update is performed for time t, we perform
the update on all structures Di such that ti > t. When a retroactive query is made
at time t, we find the largest i such that t ≥ ti , and perform on Di all updates
that occurred between times ti and t, storing information about these updates for
later rollback as in Theorem 1. We then perform the query on the resulting struc-
ture. Finally, we rollback the updates to restore the initial state of the structure
Di .
Because the data structures Di have constant indegree, we can use persistent data
structures [Driscoll et al. 1989] to reduce the space usage. Given a sequence of m
operations, we perform the sequence on a fully persistent version of the partially
retroactive
√ data structure, and keep a pointer
√ Di to the version obtained after the
first i m operations for i = 1, . . . , m. The retroactive updates √ branch off a
new version of the data structure for each modified Di . After m/2 retroactive
updates have been performed, we √ rebuild the entire structure in time O(mT (m)),
adding an amortized cost of O( mT (m)) per operation. This will ensure √ that the
number
√ of updates between any two checkpoints is always between m/2 and
3 m/2. The resulting data structure will have the claimed running times. The
fully persistent version of the partially retroactive data structure after a rebuild will
use at most O(mT (m)) space because it can use at most one √ unit of space for
each computational step. The data structure will perform at most m/2 retroactive
ACM Transactions on Algorithms, Vol. 3, No. 2, Article 13, Publication date: May 2007.
Retroactive Data Structures 11
√
updates between two rebuilds, each using at most O( m T (m)) time and extra
space, and so the space used by the fully retroactive data structure will never exceed
O(mT (m)).
4. Transformable Structures
In this section, we present some general transformations to make data structures
partially or fully retroactive for several easy classes of problems.
4.1. COMMUTATIVE OPERATIONS. To highlight the difficult case of nonlocal
effects, we define the notion of commutative operations. A set of operation types is
commutative if the state of the data structure resulting from a sequence of operations
is independent of the order of those operations.
If a data structure has a commutative set of operations, performing an operation
at any point in the past has the same effect as performing it in the present, so we
have the following lemma.
LEMMA 1. Any data structure supporting a commutative set of operations al-
lows the retroactive insertion of operations in the past (and queries in the present)
at no additional asymptotic cost.
We say that a set of operations is invertible if, for every operation u, there is
another operation u that negates the effects of operation u, that is, the sequence of
operations [u, u ] doesn’t change the state of the data structure.
LEMMA 2. Any data structure supporting a commutative and invertible set of
operations can be made partially retroactive at no additional asymptotic cost.
For example, a data structure for searchable dynamic partial sums [Raman et al.
2001] maintains an array A[1..n] of values, where sum(i) returns the sum of the first
i elements of the array, search( j) returns the smallest i such that sum(i) ≥ j, and
update(i, c) adds the value c to A[i]. The state of the data structure at the present
time is clearly independent of the order of update operations, so it is commutative.
Any operation update(i, c) is negated by the operation update(i, −c), so the updates
are also invertible, and so any data structure for searchable dynamic partial sums is
automatically partially retroactive.
An important class of commutative data structures are for searching problems.
The goal is to maintain a set S of objects under insertion and deletion operations,
so that we can efficiently answer queries Q(x, S) that ask some relation of a new
object x with the set S. Because a set S is by definition unordered, the set of
operations for a searching problem is commutative, given that the subsequence of
operations involving the same object always starts with an insertion and alternates
between insertions and deletions. As long as the retroactive updates do not violate
this consistency condition, we have the next lemma.
LEMMA 3. Any data structure for a searching problem can be made partially
retroactive at no additional asymptotic cost.
For example, not only dictionary structures, but also dynamic convex hull or
planar-width data structures, can be stated as searching problems and are thus
automatically partially retroactive. Note that these results can also be combined
with Theorem 5 to obtain fully retroactive data structures.
ACM Transactions on Algorithms, Vol. 3, No. 2, Article 13, Publication date: May 2007.
12 E. D. DEMAINE ET AL.
ACM Transactions on Algorithms, Vol. 3, No. 2, Article 13, Publication date: May 2007.
Retroactive Data Structures 13
which may also play a role in general dynamic planar point location. In fact, this
retroactive approach is hinted at as a research direction for dynamic planar point
location by Snoeyink [1997, p. 566].
ACM Transactions on Algorithms, Vol. 3, No. 2, Article 13, Publication date: May 2007.
14 E. D. DEMAINE ET AL.
updated when we add an enqueue operation at the end of the list. The front() and
back() operations return the items pointed by F and B, respectively.
LEMMA 5. There exists a fully retroactive queue data structure with all retroac-
tive operations taking time O(log m) and present-time operations taking O(1)
time.
PROOF. We maintain two order-statistic trees Te and Td [Cormen et al. 2001,
Sect. 14.1]. The tree Te stores the enqueue(x) operations sorted by time, and the
Td stores the dequeue() operations sorted by time. The update operations can then
be implemented directly in time O(log m), where m is the size of the operation
sequence currently stored.
The Query(t, “front()”) operation is implemented by querying Td to determine
the number d of dequeue() operations performed at or before time t. The operation
then returns the item in Te with time rank d + 1. The Query(t, “back()”) operation
uses te to determine the number e of enqueue() operations that were performed at
or before time t, and simply returns the item in Te with time rank e. Thus, both
queries can executed in time O(log m).
Using balanced search trees supporting updates in worst-case constant time
[Fleischer 1996], and by maintaining pointers into the trees to the current front
and back of the queues, updates and queries at the current time can be supported in
O(1) time.
5.2. DOUBLY ENDED QUEUES. A doubly ended queue (deque) maintains a list
of elements, and supports four update operations: pushL(x), popL() which inserts
or deletes an element at the left endpoint of the list, pushR(x), popR() which inserts
or deletes an element at the right endpoint of the list, and two query operations
left() and right() that return the leftmost or rightmost element in the list. The deque
generalizes both the queue and stack.
THEOREM 7. There exists a fully retroactive deque data structure with all
retroactive operations taking time O(log m) and present-time operations taking
O(1) time.
PROOF. In a standard implementation of a deque in an array A, we initialize
variables L = 1 and R = 0. Then a pushR(x) operation increments R and places
x in A[R], popR() decrements R, pushL(x) decrements L and places x in A[L],
and popL() increments L. The operation left() returns A[L] and operation right()
returns A[R].
In our retroactive implementation of a deque, we also maintain L and R: If we
maintain all pushR(x) and popR() operations in a linked list U R sorted by increasing
time and associate a weight of +1 to each pushR(x) operation and a weight of −1
to each popR(), then R at time t can be calculated as a weighted sum of a prefix
of the list up to time t. The same can be done for L, maintaining the list U L , and
reversing the weights.
The values of sums for all prefixes of U R can be maintained in the modified
(a, b)-tree of Fleischer [1996] with elements of the list as leaves. In every node of
the tree, we store the sum r of U R values within the subtree rooted at that node.
Thus, the sum of the r values of nodes hanging left of a path from the root to a
leaf is the sum of the prefix of U R up to that leaf. After inserting an element with
weight c in the list and in the tree, we set the r value in the leaf to c and walk along
ACM Transactions on Algorithms, Vol. 3, No. 2, Article 13, Publication date: May 2007.
Retroactive Data Structures 15
the path to the root, adding c to the r of all right siblings along the path. Deletions
are processed symmetrically.
Finally, we have to describe how to extract A[i] from the data structure, where
i = R at time t. For this, we augment each node of the tree with two values
containing the minimum and maximum prefix sum values for all the leaves in its
subtree. Note that these values can also be maintained after insertions and deletions
by adding c to them whenever c is added to the r value of the same node, and
updating them if an insertion occurs in their subtree.
To find the contents of A[i] at time t, we find the last time t ≤ t when R had
value i. This can be done by finding the last operation in U R before time t, walking
up the tree, and walking back down the rightmost subtree for which i is between
the minimum and maximum values. The same is done for U L .
5.3. UNION-FIND. A union-find data structure [Tarjan 1975] maintains an
equivalence relation on a set S of distinct elements, that is, a partition of S into
disjoint subsets (i.e., equivalence classes). The operation create(a) creates a new
element a in S, with its own equivalence class, union(a, b) merges the two sets that
contain a and b, and find(a) returns a unique representative element for the class
of a. Note that the representative might be different after each update, so the only
use of find(a) is to determine whether multiple elements are in the same class. The
union-find structure can be made fully retroactive, but to simplify the discussion,
we replace the find(a) operation by a sameset(a, b) operation which determines
whether a and b are in the same equivalence class.
THEOREM 8. There exists a fully retroactive union-sameset data structure sup-
porting all operations in O(log m) time.
PROOF. The equivalence relation can be represented by a forest where each
equivalence class corresponds to a tree in the forest. The create(a) operation con-
structs a new tree in the forest with a unique node a, sameset(a, b) determines
whether the root of the trees of a and b are the same, and union(a, b) assumes that
a and b are not in the same tree, sets b as the root of the tree that contains it, and
creates an edge between a and b. Such a forest can be maintained in O(log m) time
per operation using the link-cut trees of Sleator and Tarjan [1983], which maintain
a forest and support the creation and deletion of nodes, edges, and the changing of
the root of a tree.
In order to support retroactive operations, we modify the aforementioned struc-
ture by adding to each edge the time at which it was created. The link-cut tree
structure also allows finding the maximum edge value on a path between two
nodes. To determine whether two nodes are in the same set at time t, we just
have to verify that the maximum edge time on the path from a to b is no larger
than t.
5.4. PRIORITY QUEUES. More sophisticated than queues, stacks, and deques is
the priority queue which supports operations: insert(k) which inserts an element
with key value k, delete-min() which deletes the element with smallest key, and
the query find-min() which reports the current minimum-key element. The delete-
min() operation is particularly interesting here because of its dependence on all
operations in the past: Which element gets deleted depends on the set of elements
when the operation is executed. More precisely, it is delete-min() that makes the
set of operations noncommutative.
ACM Transactions on Algorithms, Vol. 3, No. 2, Article 13, Publication date: May 2007.
16 E. D. DEMAINE ET AL.
FIG. 2. The “L” representation of a sequence of operations. Pairs of corresponding insert(k) and
delete-min() operations are represented by upside-down “L” shapes. Dotted vertical lines represent
bridges.
Priority queues seem substantially more challenging than queues and stacks.
Figure 1 shows an example of the major nonlocal effects caused by a minor modi-
fication to the past in a priority queue. In particular, in this example, the lifetime of
all elements change because of a single Insert(t, “insert(k)”) operation. Such cas-
cading effects need to be succinctly represented in order to avoid the cost inherent
to any explicit maintenance of element lifetimes.
Without loss of generality, we assume that all key values inserted in the structure
are distinct. Let tk denote the insertion time of key k, and let dk denote its deletion
time. Let Q t be the set of elements contained in the priority queue at time t, and let
Q now be the set of elements in the queue at the present time. Let I≥t = {k | tk ≥ t}
be the set of keys inserted after time t, and let D≥t = {k ∈ / Q now | dk ≥ t} be the
set of keys deleted after time t.
In order to construct a retroactive priority queue, we need to learn more about
the structure of the problem. For this, we represent a sequence of updates by a
planar figure where the x axis represents time, and the y axis represents key values.
In this representation, each item k in the heap is represented by a horizontal line
segment. The left endpoint (tk , k) of this segment represents the time at which an
item is inserted into the heap and the right endpoint (dk , k) represents when the
item is removed. Similarly, a delete-min() operation is represented by a vertical ray
shooting from y = −∞ and stopping at the intersection with the horizontal segment
representing the element it deletes. Thus, insert(k) operations paired with their
corresponding delete-min() are together represented by upside-down “L” shapes,
and no two “L”s intersect, while elements still in the structure at the present time
(i.e., in Q now ) are represented by horizontal rays. See Figure 2.
One obvious invariant of a priority queue data structure is that the number |Q now |
of elements present in the queue is always equal to the number of inserts minus the
number of delete-min operations. Thus, when we add an operation u = “insert(k)”
at time t in the past, one element will have to be added in Q now . There are two
ACM Transactions on Algorithms, Vol. 3, No. 2, Article 13, Publication date: May 2007.
Retroactive Data Structures 17
FIG. 3. The Insert(t, “insert(k)”) operation causes a cascade of changes of deletion times, and one
insertion in Q now .
possibilities: If the element k is not deleted between time t and the present, k
can just be added to Q now . Otherwise, the element k is deleted by some operation
u = “delete-min()”, but then the element that was supposed to be deleted by u
will stay in the structure a little longer until deleted by some other delete-min()
operation, and so on. So, the insertion of operation u causes a cascade of changes,
depicted in Figure 3.
LEMMA 6. After an operation Insert(t, “insert(k)”), the element to be inserted
in Q now is
max(k, max k ).
k ∈D≥t
PROOF. As discussed earlier, the retroactive insertion will cause several ele-
ments to extend the time during which they are present in the structure. Consider
the chain of keys k < k1 < k2 < · · · < k whose life in the structure is extended.
After the retroactive update, the extended pieces of horizontal segments are from
(t, k) to (dk1 , k), from (dki , ki ) to (dki+1 , ki ) for i = 1, . . . , − 1, and finally from
(dk , k ) to (0, k ). They form a nondecreasing step function which, by construction,
is not properly intersected by any of the (updated) vertical rays. The key that will
be added to Q now at the end of the retroactive update is k . Suppose there is a key
k̂ larger than k in D≥t . This implies that (dk̂ , k̂) is above every segment of the step
function. But then, the vertical ray from that point intersects the step function, a
contradiction. In the particular case where k is never deleted, the step function is
just one horizontal segment and the same argument holds.
Note that removing a delete-min() operation has the same effect as reinserting
the element that was being deleted immediately after the time of the deletion. So
we have the following corollary.
COROLLARY 1. After an operation Delete(t), where the operation at time t is
“delete-min()”, the element to be inserted in Q now is
max k .
k ∈D≥t
ACM Transactions on Algorithms, Vol. 3, No. 2, Article 13, Publication date: May 2007.
18 E. D. DEMAINE ET AL.
FIG. 4. The Insert(t, “delete-min()”) operation causes a cascade of changes of deletion times, and
one deletion in Q now .
Because D≥t can change for many values of t each time an operation is performed,
it would be quite difficult to maintain explicitly. The next lemma will allow us to
avoid this task. We say that there is a bridge at time t if Q t ⊆ Q now . Bridges are
displayed as dotted vertical lines in Figure 2.
LEMMA 7. Let t be the last bridge before t. Then
max k = max k.
k ∈D≥t k ∈I≥t −Q now
PROOF. By definition of D≥t , any key k in D≥t is not in Q now . If the same k
was inserted before time t , then k ∈ Q t , but this would contradict the fact that t
is a bridge, and so k ∈ I≥t − Q now . This shows that D≥t ⊆ I≥t − Q now , and so
max k ≤ max k.
k ∈D≥t k ∈I≥t −Q now
Let k̂ = maxk ∈I≥t −Q now k , and suppose k̂ > maxk ∈D≥t k . This implies that k̂ ∈
/ D≥t ,
and so t < dk̂ < t. Because t was the last bridge before time t, dk̂ cannot be a bridge,
and so there is another key k ∈ Q dk̂ − Q now ⊆ I≥t − Q now , and k > k̂, otherwise
k would be deleted instead of k̂. But this contradicts that k̂ was maximum.
We next study the effect of adding an operation u = “delete-min()” at time t in
the past. In this case, one element will have to be removed from Q now . Again, this
operation will have a cascading effect: If it is not in Q now , the key k that will be
deleted by operation u was supposed to be deleted by the operation u at time dk ,
but as k is being deleted at time t by u, the operation u will delete the next key up,
and so on. See Figure 4.
LEMMA 8. After an operation Insert(t, “delete-min()”), the element to be re-
moved from Q now is
min k,
k∈Q t
ACM Transactions on Algorithms, Vol. 3, No. 2, Article 13, Publication date: May 2007.
Retroactive Data Structures 19
PROOF. Consider the chain of keys k1 < k2 < · · · < k < k whose life in the
structure is shortened, with ki ∈ D≥t and k ∈ Q now . After the retroactive update, the
shortened pieces of horizontal segments are from (t, k1 ) to (dk1 , k1 ), from (dki−1 , ki )
to (dki , ki ) for i = 2, . . . , , and finally from (dk , k) to (0, k). First, it must be clear
that there is a bridge at dk because there is no key smaller than k in Q dk , and all
keys larger than k in Q dk are also in Q now because k ∈ Q now . So we just have to
show that there is no bridge t between times t and dk . For this we observe that
the shortened segments at times t ∈ [t, dk ) form a step function, and that none of
the keys ki corresponding to the steps are in Q now , but they are in Q t .
Because removing an “insert(k)” operation from time t has the same effect as
adding a “delete-min()” operation directly before the time where it is deleted (if
that happens), we also have the next corollary.
COROLLARY 2. After an operation Delete(t) where the operation at time t is
u t = “insert(k)”, the element to be removed from Q now is k if k ∈ Q now ; otherwise,
it is
min k ,
k ∈Q t
ACM Transactions on Algorithms, Vol. 3, No. 2, Article 13, Publication date: May 2007.
20 E. D. DEMAINE ET AL.
O(log m) time per retroactive update because each update changes at most one
element of Q now .
ACKNOWLEDGMENTS. We thank Michael Bender, Prosenjit Bose, Jean Cardinal,
Alejandro López-Ortiz, Ian Munro, and the anonymous referees for helpful discus-
sions and comments.
REFERENCES
BENTLEY, J. 1977. Algorithms for Klee’s rectangle problems. unpublished manuscript, Department of
Computer Science, Carnegie-Mellon University.
BENTLEY, J. L., AND SAXE, J. B. 1980. Decomposable searching problems I: Static-to-Dynamic trans-
formations. J. Alg. 1, 301–358.
CORMEN, T. H., LEISERSON, C. E., RIVEST, R. L., AND STEIN, C. 2001. Introduction to Algorithms, 2nd
ed. MIT Press, Cambridge, MA.
DRISCOLL, J. R., SARNAK, N., SLEATOR, D. D., AND TARJAN, R. E. 1989. Making data structures persis-
tent. J. Comput. Syst. Sci. 38, 1, 86–124.
FIAT, A. AND KAPLAN, H. 2001. Making data structures confluently persistent. In Proceedings of the
12th Annual Symposium on Discrete Algorithms (Washington, DC) 537–546.
FLEISCHER, R. 1996. A simple balanced search tree with O(1) worst-case update time. Int. J. Found.
Comput. Sci. 7, 2, 137–149.
FRANDSENA, G. S., HANSENB, J. P., AND MILTERSEN, P. B. 2001. Lower bounds for dynamic algebraic
problems. Inf. Comput. 171, 2 (Dec.), 333–349.
GOODRICH, M. AND TAMASSIA, R. 1991. Dynamic trees and dynamic point location. In Proceedings of
the 23rd Annual ACM Symposium on Theory Computing. 523–533.
MANNILA, H. AND UKKONEN, E. 1986. The set union problem with backtracking. In Proceedings of the
13th International Conference on Automata, Languages and Programming (ICALP). Lecture Notes in
Computer Science, vol. 226. Springer Verlag, Berlin. 236–243.
ORWELL, G. 1949. 1984. Signet Classic.
PĂTRASCU, M. AND DEMAINE, E. D. 2004. Tight bounds for the partial-sums problem. In Proceedings
of the 15th Annual ACM-SIAM Symposium on Discrete Algorithms. (New Orleans, LA). 20–29.
RAMAKRISHNAN, R. AND GEHRKE, J. 2002. Database Management Systems. McGraw-Hill, New York.
RAMAN, R., RAMAN, V., AND RAO, S. S. 2001. Succinct dynamic data structures. In Proceedings of
the 7th Workshop on Algorithms and Data Structures. Lecture Notes in Computer Science, vol. 2125.
Springer Verlag, Berlin. 426–437.
SARNAK, N. AND TARJAN, R. E. 1986. Planar point location using persistent search trees. Commun.
ACM 29, 7 (Jul.), 669–679.
SLEATOR, D. D. AND TARJAN, R. E. 1983. A data structure for dynamic trees. J. Comput. Syst. Sci. 26, 3,
362–381.
SNOEYINK, J. 1997. Point location. In Handbook of Discrete and Computational Geometry, J. E. Good-
man and J. O’Rourke, eds. CRC Press, Boca Raton, FL. 559–574.
STRASSEN, V. 1990. Algebraic complexity theory. In Algorithms and Complexity, J. van Leeuwen, ed.
Handbook of Theoretical Computer Science, vol. A. MIT Press, Cambridge, MA. 633–672.
TARJAN, R. E. 1975. Efficiency of a good but not linear set union algorithm. J. ACM 22, 215–225.
TARJAN, R. E. 1979. A class of algorithms which require nonlinear time to maintain disjoint sets. J.
Comput. Syst. Sci. 18, 110–127.
WESTBROOK, J. AND TARJAN, R. E. 1989. Amortized analysis of algorithms for set union with back-
tracking. SIAM J. Comput. 18, 1–11.
YAO, A. C. 1981. Should tables be sorted? J. ACM 28, 3, 615–628.
ACM Transactions on Algorithms, Vol. 3, No. 2, Article 13, Publication date: May 2007.