Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Link Cut Tree #124

Open
wants to merge 15 commits into
base: main
Choose a base branch
from

Conversation

PotatoHashing
Copy link

This PR is about updating the Link Cut Tree. Most of it is from MIT's LCT. This new version easily supports dynamic links and cuts, as well as queries and updates on paths (like HLD). The code has been separated so that the functions in the Node struct will change the structure of the LCT (access, splay, rotate, etc) and the functions under LinkCut will call those under Node to perform queries and updates about the tree. Alternatively, the functions under LinkCut are meant to be called by a user directly (e.g. in main) while the functions in Node aren't.

The key points are:

  1. Access(u) before updating/querying a node u.
  2. Make root(u) and access(v) before updating/querying a path.

The current code shows an example on how to update a point on a path and query for max on a path. (It basically solves http://acm.timus.ru/problem.aspx?num=1553).

Some current possible issues.

  1. xiao can probably be renamed. xiao(x) basically does "go up the current splay tree that x is in, and make all nodes on that path have the same path parent as the root of that splay tree".
  2. Mixture of "." and "->" in LinkCut due to sometimes using Node and other time using Node*. Might be helpful to standardize.
  3. /// start-hash and /// end-hash were left over from MIT.
  4. Cut and link use makeRoot to simplify their implementations. This means that if a represented tree has fixed root, it would be necessary to call an additional makeRoot to reroot the tree correctly after each link/cut. This could also be an issue for problems of HLD on edges where the value of a node stores the value of the edge from that node to its parent. (Although in the HLD case, we can just create N-1 additional nodes, one for each edge). I've tried to see what changes need to be made to represent a fixed rooted LCT, but it seems non trivial at the moment.

Future work.
There's this blog on applications on LCT. It might be useful to include parts of that. Unfortunately, I can't read Chinese, so I'm leaving this incomplete for now.
https://www.cnblogs.com/flashhu/p/8324551.html

I am open to questions and suggestions.

@PotatoHashing
Copy link
Author

PotatoHashing commented Jul 2, 2019

Also, this LCT doesn't fix #117. It would need the changes from https://codeforces.com/blog/entry/67637 or the Chinese blog.

content/graph/LCT.h Outdated Show resolved Hide resolved
* Current implementation supports update value at a node,
* and query max on a path.
* Tested on: http://acm.timus.ru/problem.aspx?num=1553
* Status: Passes existing fuzz tests (with function names modified).
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We'll want to remove the old link-cut tree, so feel free to do that and modify the fuzz-test. Will also need to update the test to verify that max works (with max replaced by some non-commutative, non-associative function)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated the fuzz-test to verify max for now. Will update it later for any new function that we decide on...

content/graph/LCT.h Outdated Show resolved Hide resolved
if(c[1]) c[1]->flip ^= 1;
swap(c[0], c[1]); flip = 0;
}
// add stuff
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove this comment as well -- I think we can instead write in the description how to augment it ("extend push/pull").

We'll also want a more thorough explanation and/or example -- it's not clear to me in which ways the LCT is similar to a segment tree. E.g. how do I do lazy updates on entire paths in the tree? Entire subtrees? Queries on subtrees? Can I use the flip bit myself for anything? How are things ordered? It's not reasonable to answer all of these questions (we should have a link in the description!), but some more info would be useful.

cval = val;
if(c[0]) c[0]->push(), cval = max(cval, c[0]->cval);
if(c[1]) c[1]->push(), cval = max(cval, c[1]->cval);
// add stuff
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this work with non-commutative and non-associative operations?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We've talked about this elsewhere, but it should work for non-commutative, associative functions (like a segment tree).

content/graph/LCT.h Outdated Show resolved Hide resolved
content/graph/LCT.h Outdated Show resolved Hide resolved
content/graph/LCT.h Outdated Show resolved Hide resolved
content/graph/LCT.h Outdated Show resolved Hide resolved
if (z) z->pull();
y->pull();
} /// end-hash
void xiao() {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree that we should probably rename this

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"propogatePathParent" is a little much though... Will keep thinking about possible alternatives.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could certainly shorten that to propPP if that's what we want to get across. But a nonsensical name would be fine as well

@simonlindholm
Copy link
Member

Neat. I think the main thing I would want out of this is a more detailed view of how it can be augmented. We should try not to bloat it too much with unnecessary cruft, but right now it's hard for me to understand how to augment it with non-trivial custom stuff.

I wouldn't worry too much about point 4 if it's hard to figure out, keeping it simple is good. And I don't think mixing . and -> is a problem.

@PotatoHashing
Copy link
Author

I forgot to push my most recent changes before making the PR. It's pushed now.

@Chillee
Copy link
Collaborator

Chillee commented Jan 8, 2020

@PotatoHashing would you still like to finish this PR? I want to get a LCT implementation - perhaps ideally this one. Alternately, I could take over for this PR if you're busy.

@PotatoHashing
Copy link
Author

We discussed this on Discord but I should probably repeat it here. Feel free to take this over @Chillee (or anyone else interested).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants