BZOJ4825 [Hnoi2017]单旋 【线段树】
题目链接
题解
手模一下操作,会发现一些很优美的性质:
每次旋到根,只有其子树深度不变,剩余点深度\(+1\)
每次旋到根,【最小值为例】右儿子接到其父亲的左儿子,其余点形态不改变,然后将该点接到根之上,原根变为其右儿子
每次插入,都是插入到其前驱后继深度较大的那一个点之下
所以我们很容易模拟出树的形态,同时用线段树维护离散化后各权值的深度
#include<iostream>
#include<cstdio>
#include<cmath>
#include<set>
#include<cstring>
#include<algorithm>
#define LL long long int
#define Redge(u) for (int k = h[u],to; k; k = ed[k].nxt)
#define REP(i,n) for (int i = 1; i <= (n); i++)
#define BUG(s,n) for (int i = 1; i <= (n); i++) cout<<s[i]<<' '; puts("");
using namespace std;
const int maxn = 100005,maxm = 100005,INF = 1000000000;
inline int read(){
int out = 0,flag = 1; char c = getchar();
while (c < 48 || c > 57){if (c == '-') flag = -1; c = getchar();}
while (c >= 48 && c <= 57){out = (out << 3) + (out << 1) + c - 48; c = getchar();}
return out * flag;
}
set<int> S;
struct Que{
int opt,v;
}Q[maxn];
int fa[maxn],ls[maxn],rs[maxn];
int b[maxn],tot,m;
int getn(int x){return lower_bound(b + 1,b + 1 + tot,x) - b;}
int val[maxn << 2],tag[maxn << 2];
void pd(int u){
if (tag[u]){
val[u << 1] += tag[u]; tag[u << 1] += tag[u];
val[u << 1 | 1] += tag[u]; tag[u << 1 | 1] += tag[u];
tag[u] = 0;
}
}
void change(int u,int l,int r,int pos,int v){
if (l == r) {val[u] = v; return;}
pd(u);
int mid = l + r >> 1;
if (mid >= pos) change(u << 1,l,mid,pos,v);
else change(u << 1 | 1,mid + 1,r,pos,v);
}
void modify(int u,int l,int r,int L,int R,int v){
if (l >= L && r <= R) {val[u] += v; tag[u] += v; return;}
pd(u);
int mid = l + r >> 1;
if (mid >= L) modify(u << 1,l,mid,L,R,v);
if (mid < R) modify(u << 1 | 1,mid + 1,r,L,R,v);
}
int query(int u,int l,int r,int pos){
if (l == r) return val[u];
pd(u);
int mid = l + r >> 1;
if (mid >= pos) return query(u << 1,l,mid,pos);
return query(u << 1 | 1,mid + 1,r,pos);
}
void print(int u,int l,int r){
if (l == r) printf("%d ",val[u]);
else {
pd(u);
int mid = l + r >> 1;
print(u << 1,l,mid);
print(u << 1 | 1,mid + 1,r);
}
}
int main(){
m = read(); int n = 0;
REP(i,m){
Q[i].opt = read();
if (Q[i].opt == 1) b[++n] = Q[i].v = read();
}
sort(b + 1,b + 1 + n); tot = 1;
for (int i = 2; i <= n; i++) if (b[i] != b[tot]) b[++tot] = b[i];
S.insert(0); S.insert(tot + 10);
int pre,nxt,d1,d2,u,v,rt;
for (int i = 1; i <= m; i++){
if (Q[i].opt == 1){
u = getn(Q[i].v);
S.insert(u);
pre = *--S.find(u);
nxt = *++S.find(u);
if (pre == 0 && nxt == tot + 10)
change(1,1,tot,u,1),rt = u;
else if (pre == 0){
d1 = query(1,1,tot,nxt);
change(1,1,tot,u,d1 + 1);
fa[u] = nxt; ls[nxt] = u;
}
else if (nxt == tot + 10){
d2 = query(1,1,tot,pre);
change(1,1,tot,u,d2 + 1);
fa[u] = pre; rs[pre] = u;
}
else {
d1 = query(1,1,tot,nxt);
d2 = query(1,1,tot,pre);
if (d1 > d2){
change(1,1,tot,u,d1 + 1);
fa[u] = nxt; ls[nxt] = u;
}
else {
change(1,1,tot,u,d2 + 1);
fa[u] = pre; rs[pre] = u;
}
}
ls[u] = rs[u] = 0;
printf("%d\n",query(1,1,tot,u));
}
else if (Q[i].opt == 2){
u = *++S.find(0);
printf("%d\n",query(1,1,tot,u));
if (!fa[u]) continue;
modify(1,1,tot,fa[u],tot,1);
change(1,1,tot,u,1);
v = fa[u];
ls[v] = rs[u]; if (rs[u]) fa[rs[u]] = v;
rs[u] = rt; fa[rt] = u; fa[u] = 0;
rt = u;
}
else if (Q[i].opt == 3){
u = *--S.find(tot + 10);
printf("%d\n",query(1,1,tot,u));
if (!fa[u]) continue;
modify(1,1,tot,1,fa[u],1);
change(1,1,tot,u,1);
v = fa[u];
rs[v] = ls[u]; if (ls[u]) fa[ls[u]] = v;
ls[u] = rt; fa[rt] = u; fa[u] = 0;
rt = u;
}
else if (Q[i].opt == 4){
u = *++S.find(0);
printf("%d\n",query(1,1,tot,u));
if (fa[u]) modify(1,1,tot,u,fa[u] - 1,-1);
else modify(1,1,tot,1,tot,-1);
if (v = fa[u]){
ls[v] = rs[u]; if (rs[u]) fa[rs[u]] = v;
rs[u] = 0;
}
else if (rs[u]) fa[rs[u]] = 0,rt = rs[u],rs[u] = 0;
S.erase(u);
}
else if (Q[i].opt == 5){
u = *--S.find(tot + 10);
printf("%d\n",query(1,1,tot,u));
if (fa[u]) modify(1,1,tot,fa[u] + 1,u,-1);
else modify(1,1,tot,1,tot,-1);
if (v = fa[u]){
rs[v] = ls[u]; if (ls[u]) fa[ls[u]] = v;
ls[u] = 0;
}
else if (ls[u]) fa[ls[u]] = 0,rt = ls[u],ls[u] = 0;
S.erase(u);
}
/*printf("rt = %d\n",b[rt]);
for (int i = 1; i <= tot; i++){
printf("node%d fa = %d ,ls = %d rs = %d\n",b[i],b[fa[i]],b[ls[i]],b[rs[i]]);
}
print(1,1,tot); puts("");*/
}
return 0;
}
BZOJ4825 [Hnoi2017]单旋 【线段树】的更多相关文章
- [BZOJ4825][HNOI2017]单旋(线段树+Splay)
4825: [Hnoi2017]单旋 Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 667 Solved: 342[Submit][Status][ ...
- 【BZOJ4825】[Hnoi2017]单旋 线段树+set
[BZOJ4825][Hnoi2017]单旋 Description H 国是一个热爱写代码的国家,那里的人们很小去学校学习写各种各样的数据结构.伸展树(splay)是一种数据结构,因为代码好写,功能 ...
- 【bzoj4825】[Hnoi2017]单旋 线段树+STL-set
题目描述 H 国是一个热爱写代码的国家,那里的人们很小去学校学习写各种各样的数据结构.伸展树(splay)是一种数据结构,因为代码好写,功能多,效率高,掌握这种数据结构成为了 H 国的必修技能.有一天 ...
- BZOJ.4825.[AHOI/HNOI2017]单旋(线段树)
BZOJ LOJ 洛谷 这题不难啊,我怎么就那么傻,拿随便一个节点去模拟.. 我们只需要能够维护,将最小值或最大值转到根.模拟一下发现,对于最小值,它的右子树深度不变(如果存在),其余节点深度全部\( ...
- 洛谷P3721 [AH2017/HNOI2017]单旋(线段树 set spaly)
题意 题目链接 Sol 这题好毒瘤啊.. 首先要观察到几个性质: 将最小值旋转到根相当于把右子树变为祖先的左子树,然后将原来的根变为当前最小值 上述操作对深度的影响相当于右子树不变,其他的位置-1 然 ...
- bzoj4825 [Hnoi2017]单旋
Description H 国是一个热爱写代码的国家,那里的人们很小去学校学习写各种各样的数据结构.伸展树(splay)是一种数据结构,因为代码好写,功能多,效率高,掌握这种数据结构成为了 H 国的必 ...
- BZOJ4825: [Hnoi2017]单旋(Splay)
题面 传送门 题解 调了好几个小时--指针太难写了-- 因为只单旋最值,我们以单旋\(\min\)为例,那么\(\min\)是没有左子树的,而它旋到根之后,它的深度变为\(1\),它的右子树里所有节点 ...
- [BZOJ4825][HNOI2017]单旋spaly
BZOJ Luogu 题目太长了,就不放了. 题解 首先声明一点,无论是splay还是spaly,插入一个新的元素,都要rotate到根!所以说题目也算是给了一个错误示范吧. 我们发现把最值旋转到根并 ...
- 4825: [Hnoi2017]单旋
4825: [Hnoi2017]单旋 链接 分析: 以后采取更保险的方式写代码!!!81行本来以为不特判也可以,然后就总是比答案大1,甚至出现负数,调啊调啊调啊调~~~ 只会旋转最大值和最小值,以最小 ...
随机推荐
- js加减乘除精确计算
Javascript精确计算时的bug JS无法进行精确计算的bug 在做CRM,二代审核需求审核详情页面时.需要按比例(后端传类似0.8的小数)把用户输入的数字显示在不同的地方. 在做dubheIn ...
- Windows平台下源码分析工具
最近这段时间在阅读 RTKLIB的源代码,目前是将 pntpos.c文件的部分看完了,准备写一份文档记录下这些代码的用处.处理过程.理论公式来源.注意事项,自己还没有弄明白的地方.目前的想法是把每一个 ...
- mysql 自增主键为什么不是连续的?
由于自增主键可以让主键索引尽量地保持递增顺序插入,避免了页分裂,因此索引更紧凑 MyISAM 引擎的自增值保存在数据文件中 nnoDB 引擎的自增值,其实是保存在了内存里,并且到了 MySQL 8.0 ...
- 什么是shell 是不是什么时候都可以使用shell
因为Shell似乎是各UNIX系统之间通用的功能,并且经过了POSIX的标准化.因此,Shell脚本只要"用心写"一次,即可应用到很多系统上.因此,之所以要使用Shell脚本是基于 ...
- 红帽CentOS7 密码破解
1.在启动的时候按住方向键停留在内核选项页面,在内核选项出按e键 2.进入到另一个页面后,寻找到以linux16开头的地方,按end到行后,输入空格,然后输入rd.break console=tty0 ...
- 使用 python快速搭建http服务
在 Linux 服务器上或安装了 Python 的机器上,Python自带了一个WEB服务器 SimpleHTTPServer. 我们可以很简单的使用 python -m SimpleHTTPSer ...
- html5的canvas绘制线条,moveTo和lineTo详解
今天在看html5,里面新增的属性有一个canvas,它相当于一个画布你可以用js在里面画你想要的效果!我在w3c的手册里面看到用moveTo和lineTo绘制线条讲的不是很清楚,尤其是moveTo和 ...
- hadoop的shuffle过程
1. shuffle: 洗牌.发牌——(核心机制:数据分区,排序,缓存): shuffle具体来说:就是将maptask输出的处理结果数据,分发给reducetask,并在分发的过程中,对数据按key ...
- HAN模型理解2
Hierarchical Attention Networks for Document Classification 论文的理解 在论文的摘要中,它提出了论文的两个特点.第一个就是对应文章所有具有的 ...
- POJ:2431-Expedition
Expedition Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 20089 Accepted: 5786 Descripti ...