hdu2475Box(splay树形转线性)

链接

推荐一篇帖子

http://blog.csdn.net/lyhypacm/article/details/6734748

这题暴力不可行主要是因为这颗树可能极度不平衡,不能用并查集是不能路径压缩,这样时间复杂度是很高的。

可以用伸展树主要是因为它的伸展性,每次操作后可以通过伸展使这棵树更好的保持平衡。

这题还是值得记录一下的,从早上做到了晚上,

第一次错误,定义了全局的n以及局部的n使得取得结果不正确,以后还是统一习惯,要么写在全局要么写在局部。

第二次错误,vector初始化没有初始到0导致后面的数据跑不动,以后初始化的操作都从0开始。

第三次错误,debug了n久,建树的时候误把根节点的父亲节点写成了根,应该是0,自以为不会出错的地方也要认真检查。

  1 #include <iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<algorithm>
  5 #include<stdlib.h>
  6 #include<vector>
  7 #include<cmath>
  8 #include<queue>
  9 #include<set>
 10 #include<stack>
 11 using namespace std;
 12 #define N 100010
 13 #define LL long long
 14 #define INF 0xfffffff
 15 const double eps = 1e-8;
 16 const double pi = acos(-1.0);
 17 const double inf = ~0u>>2;
 18 int n,po[N];
 19 vector<int>ed[N];
 20 vector<int>dd;
 21
 22 struct splay_tree
 23 {
 24     int pre[N];
 25     int ch[N][2];
 26     int root,tot,num;
 27     int key[N];
 28 //    void dfs(int x)
 29 //    {
 30 //        if(x)
 31 //        {
 32 //            dfs(ch[x][0]);
 33 //            printf("结点%2d:左儿子 %2d 右儿子 %2d 父结点 %2d size=%2d,key=%2d\n",
 34 //                   x,ch[x][0],ch[x][1],pre[x],size[x],key[x]);
 35 //            dfs(ch[x][1]);
 36 //        }
 37 //    }
 38 //    void debug()
 39 //    {
 40 //        printf("root:%d\n",root);
 41 //        dfs(root);
 42 //    }
 43 //以上用于debug*/
 44     void newnode(int &x,int v,int fa)//新建一结点
 45     {
 46         x = ++tot;
 47         ch[x][0]=ch[x][1] = 0;
 48         pre[x] = fa;
 49         key[x] = v;
 50         po[v] = x;
 51     }
 52     void pushup(int w)//由儿子更新其父亲
 53     {
 54     }
 55     void rotate(int r,int kind)//旋转操作,根据kind进行左旋和右旋
 56     {
 57         int y = pre[r];
 58         ch[y][!kind] = ch[r][kind];
 59         pre[ch[r][kind]] = y;
 60         if(pre[y])
 61         {
 62             ch[pre[y]][ch[pre[y]][1]==y] = r;
 63         }
 64         pre[r] = pre[y];
 65         ch[r][kind] = y;
 66         pre[y] = r;
 67         pushup(y);
 68         pushup(r);
 69     }
 70     void splay(int r,int goal)//将r结点旋至goal下
 71     {
 72         while(pre[r]!=goal)
 73         {
 74             if(pre[pre[r]]==goal)
 75             {
 76                 rotate(r,ch[pre[r]][0]==r);
 77             }
 78             else
 79             {
 80                 int y = pre[r];
 81                 int kind = (ch[pre[y]][0]==y);
 82                 if(ch[y][kind]==r)
 83                 {
 84                     rotate(r,!kind);
 85                     rotate(r,kind);
 86                 }
 87                 else
 88                 {
 89                     rotate(y,kind);
 90                     rotate(r,kind);
 91                 }
 92             }
 93         }
 94         pushup(r);
 95         if(goal==0) root = r;
 96     }
 97     int get_min(int x)
 98     {
 99         while(ch[x][0])
100             x =  ch[x][0];
101         return x;
102     }
103     int get_max(int x)
104     {
105         while(ch[x][1])
106             x = ch[x][1];
107         return x;
108     }
109     void update(int x,int y) //更新区间信息
110     {
111         int l = po[x],r = po[x+n];
112         splay(l,0);
113         splay(r,0);
114         int ll = ch[l][0];
115         int rr = ch[r][1];
116         pre[ll] = pre[rr] = 0;
117         ch[r][1] = ch[l][0] = 0;
118
119         int tll = get_max(ll);
120         if(tll!=0)
121             ch[tll][1] = rr;
122         pre[rr] = tll;
123
124         if(y==0) return ;
125         if(query(y)==x)
126         {
127             ch[r][1] = rr;
128             ch[l][0] = ll;
129             pre[ll] = l;
130             pre[rr] = r;
131             ch[tll][1] = 0;
132             pre[0] = 0;
133             return ;
134         }
135
136         if(rr!=0) splay(rr,0);
137         int tt = po[y];
138         splay(tt,0);
139         int tq = get_min(ch[tt][1]);
140         splay(tq,tt);
141         ch[tq][0] = r;
142         pre[r] = tq;
143     }
144     int query(int x)//询问l,r区间,将第l-1个结点旋自根,第r+1个结点旋自根的有儿子,
145     {
146         splay(po[x],0);
147         int k = get_min(po[x]);
148         return key[k];
149     }
150     void build(int &x,int l,int r,int fa)
151     {
152         int m = (l+r)>>1;
153         if(l>r) return ;
154         newnode(x,dd[m],fa);
155         build(ch[x][0],l,m-1,x);
156         build(ch[x][1],m+1,r,x);
157         pushup(x);
158     }
159     void init()
160     {
161         root = tot = 0;
162         memset(ch,0,sizeof(ch));
163         memset(pre,0,sizeof(pre));
164         memset(key,0,sizeof(key));
165         memset(po,0,sizeof(po));
166     }
167 } SP;
168 void dfs(int u)
169 {
170     int i;
171     dd.push_back(u);
172     for(i = 0; i  < ed[u].size(); i++)
173     {
174         int v = ed[u][i];
175         dfs(v);
176     }
177     dd.push_back(u+n);
178 }
179 int main()
180 {
181     int i;
182     int q;
183     int mark = false;
184     while(scanf("%d",&n)!=EOF)
185     {
186         if(mark)
187             puts("");
188         else
189             mark = true;
190         SP.init();
191         for(i = 0; i <= n; i++)
192         {
193             ed[i].clear();
194         }
195         dd.clear();
196         for(i = 1; i <= n; i++)
197         {
198             int x;
199             scanf("%d",&x);
200             ed[x].push_back(i);
201         }
202         dfs(0);
203         int o = 1;
204         scanf("%d",&q);
205         stack<int>st;
206         for(i = 1 ; i < dd.size()-1 ; i++)
207         {
208             int x = dd[i];
209             if(x<=n) st.push(x);
210             else st.pop();
211             if(st.empty())
212             {
213                 SP.build(SP.root,o,i,0);
214                 o = i+1;
215             }
216         }
217         int stt = 1;
218         while(q--)
219         {
220             char sq[100];
221             int x,y;
222             scanf("%s",sq);
223             if(sq[0]==‘Q‘)
224             {
225                 scanf("%d",&x);
226                 printf("%d\n",SP.query(x));
227             }
228             else
229             {
230                 scanf("%d%d",&x,&y);
231                 SP.update(x,y);
232             }
233         }
234     }
235     return 0;
236 }

hdu2475Box(splay树形转线性),布布扣,bubuko.com

时间: 2024-10-11 13:34:43

hdu2475Box(splay树形转线性)的相关文章

树链剖分——树形到线性的转化

树链剖分: 树上操作并不能实现一段链的直接更新. 树链剖分就解决了这个问题. 本质上是树形到线性的转化. 通过子树,重链是一个连续的dfn区间的优秀性质,可以在dfn序列上进行操作,达到在树上操作的目的. 通常和线段树结合. 板子:以前写的. 树链剖分 例题: 1.遥远的国度 题目大意: 给定一棵有根树,每个点有一个权值,提供三种操作: 1.将x节点变为根节点 2.将x到y路径上的点的权值全部改为v 3.询问x的子树中点权的最小值 如果根不变,那么2.3就直接做了. 但是根变化了,随之第三问,子

CodeForces 466E Information Graph --树形转线性+并查集

题意:有三种操作: 1.新增一条边从y连向x,此前x没有父节点 2.x接到一份文件,(文件标号逐次递增),然后将这份文件一路上溯,让所有上溯的节点都接到这份文件 3.查询某个节点x是否接到过文件F 解法: 首先要知道一个性质,节点u在v的上溯路径上的话要满足: L[u]<=L[v] && R[u] >= R[v] (先进后出) 先将所有的边都读入,dfs得出L[u],R[u],然后将查询分为tot类(tot=总文件种数),记录每一类有那些地方查询了,然后如果type=2,那么记

线性结构与树形结构相互转换(ES6实现)

前言 当树形结构的层级越来越深时,操作某一节点会变得越来越费劲,维护成本不断增加.所以线性结构与树形的相互转换变得异常重要! 首先,我们约定树形结构如下: node = { id: number, // 数值 parentId: number, // 数值 name: string, children: [] || null, // 用数组的方式保存子节点,适合更多业务场景 }   线性结构: list = [ { id: number, parentId: number, name: stri

第一阶段:Java内功秘籍-线性表

前言 为什么要学习数据结构与算法,如果你学会了做安卓,javaweb,前端等,都是你的武功秘籍,但是如果你的内功不够好,再厉害的功夫也是白费. 数据结构和算法:什么是数据结构,什么是数据,在计算机内部数据为01010101...,数据是我们生活中一切的事务都可以表示为数据,如你和你朋友聊天的话都是数据,朋友圈的发表内容也是内容. 数据结构是数据之间相互存在的一种或多种特定的关系,数据之间的关系.数据结构的关系,要么一对一,或者一对多. er图,实体关联图.数据与数据之间的关系,分: 图形结构 树

Codeforces Round #316 (Div. 2) D Tree Requests

官方题解是离线询问,dfs树形转线性,然后二分找区间. 还有一种比较好的做法是直接dfs,将当前访问这个结点u相关的询问之前的状态存起来,然后访问完以后利用异或开关性,得到这颗子树上的答案. 代码是学习别人的http://blog.csdn.net/squee_spoon/article/details/47666667 当时做的时候想得是树形转线性,觉得dfs会暴栈,想用bfs,之前又没写过,于是愣了一个钟头. #include<bits/stdc++.h> using namespace

2014上海网络预选赛1003(树链剖分)HDU5044

Tree Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 700    Accepted Submission(s): 145 Problem Description You are given a tree (an acyclic undirected connected graph) with N nodes. The tree

Kuangbin 带你飞-线段树专题 题解

HDU 1166 敌兵布阵 单调更新区间查询和 #include <map> #include <set> #include <list> #include <cmath> #include <ctime> #include <deque> #include <stack> #include <queue> #include <cctype> #include <cstdio> #inc

树链剖分[模板](洛谷 P3384)

洛谷·[模板]树链剖分 写在前面 首先,在学树链剖分之前最好先把 LCA.树形DP.DFS序 这三个知识点学了 如果这三个知识点没掌握好的话,树链剖分难以理解也是当然的. 树链剖分 树链剖分 就是对一棵树分成几条链,把树形变为线性,减少处理难度 概念 dfs1() dfs2() 对剖过后的树建线段树 处理问题 概念 重儿子:对于每一个非叶子节点,它的儿子中 儿子数量最多的那一个儿子 为该节点的重儿子 轻儿子:对于每一个非叶子节点,它的儿子中 非重儿子 的剩下所有儿子即为轻儿子 叶子节点没有重儿子

POJ 3321 Apple Tree 【树形结构转变为线性结构+线段树OR树状数组】

Apple Tree Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 21587   Accepted: 6551 POJ 3321链接: Description There is an apple tree outside of kaka's house. Every autumn, a lot of apples will grow in the tree. Kaka likes apple very much, so