codeforces Gym 100431G Persistent Queue
2015-08-17 23:44
405 查看
啥都别说了!真心好题!在线在树上找LCA的关键地方就在于这个,一定要好好理解它!
第i个操作: 1...v..c
这个操作的头结点就等于 v 这个操作的头结点,尾节点就等于 i;
第i个操作: −1...v
这个操作的尾节点就等于 v 这个操作的尾结点,要删除的数明显就是操作 v 的头结点所对应的数,但是删除完后呢?别忘了我们还没有维护这个操作的头结点,也就是第v个操作得到的序列删除第一个数后的头结点,如何去找呢?
方法就是 : 从这个操作的尾节点开始往上找到离头节点最近的那个点就是我们所要维护的头结点了,但是直接往上找肯定是会T的!
所以这个就是该题的关键所在了—–如何从某个点 U 开始往上找到树上离点 V 最近的那个点,要求复杂度—O(log)
方法 : dp[i][j] 表示节点 i 往上走 2j 后节点是多少,那么通过简单的转移就能得到我们想要找到的节点了。
代码来自潘教练,自己简单的注释了一下!
题意:
给一些操作,包括在末尾加一个数或者是删除最前面的一个数,而每次操作是先复制第v个操作留下的序列,再进行加数或删除数的操作,最后得到一个新的序列。问每次删除的数是多少!思路:
比较容易想到的是:把这些操作看做树上的点,对每一个操作都去维护一下它的头节点和尾节点。第i个操作: 1...v..c
这个操作的头结点就等于 v 这个操作的头结点,尾节点就等于 i;
第i个操作: −1...v
这个操作的尾节点就等于 v 这个操作的尾结点,要删除的数明显就是操作 v 的头结点所对应的数,但是删除完后呢?别忘了我们还没有维护这个操作的头结点,也就是第v个操作得到的序列删除第一个数后的头结点,如何去找呢?
方法就是 : 从这个操作的尾节点开始往上找到离头节点最近的那个点就是我们所要维护的头结点了,但是直接往上找肯定是会T的!
所以这个就是该题的关键所在了—–如何从某个点 U 开始往上找到树上离点 V 最近的那个点,要求复杂度—O(log)
方法 : dp[i][j] 表示节点 i 往上走 2j 后节点是多少,那么通过简单的转移就能得到我们想要找到的节点了。
代码来自潘教练,自己简单的注释了一下!
#include<cstdio> #include<algorithm> #include<iostream> using namespace std; int n; #define N 200010 int dp [20],val ; struct Oper{ int t1, t2; int dep; }op ; int main(){ freopen("queue.in","r",stdin); freopen("queue.out","w",stdout); //初始化 scanf("%d",&n); for(int i = 0; i <= n; i++){ for(int j = 0; 1 << j <= n; j++){ dp[i][j] = -1; } } int log; for(log = 0; 1 << log <= n; log++); log--; op[0].t1 = 0, op[0].t2 = 0, op[0].dep = 0; for(int i = 1; i <= n; i++) { int ty; scanf("%d",&ty); if(ty == 1) { int v, x; scanf("%d%d",&v,&x); val[i] = x; dp[i][0] = op[v].t2; for(int j = 1; 1 << j <= n; j++) { if(dp[i][j-1] != -1) dp[i][j] = dp[ dp[i][j-1] ][j-1]; } op[i].t1 = op[v].t1; op[i].t2 = i; op[i].dep = op[ dp[i][0] ].dep + 1; } else if(ty == -1) { int v; scanf("%d",&v); op[i] = op[v]; //关键代码,log复杂度内找到 //同时记录每个节点对应的深度,加上深度的判断就行了! int t = op[i].t2; for(int j = log; j >= 0; j--){ if(dp[t][j] != -1 && op[ dp[t][j] ].dep > op[ op[i].t1 ].dep) { t = dp[t][j]; } } printf("%d\n",val[t]); op[i].t1 = t;//成功维护好头节点 } } return 0; }
相关文章推荐
- C#实现获取系统目录并以Tree树叉显示的方法
- C语言实现输入一颗二元查找树并将该树转换为它的镜像
- 纯jsp打造无限层次的树代码
- php遍历树的常用方法汇总
- PHP树的深度编历生成迷宫及A*自动寻路算法实例分析
- PHP生成树的方法
- Java Swing中的表格(JTable)和树(JTree)组件使用实例
- python数据结构树和二叉树简介
- B+树到MySQL之innoDB
- ExtJS 4 树
- 数据库表TreeView树的快速生成
- Oracle 查询所有的父节点和子节点
- 树的双亲存储:
- 树
- 二叉树(2)——遍历的非递归实现
- 二叉树(2)——遍历的非递归实现
- 二叉树(3)——三叉链表示的二叉树
- C#实现树结构
- Java数据结构-二叉树及其遍历
- Android树状列表实现