日总结——20180303

Posted hinanawitenshi

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了日总结——20180303相关的知识,希望对你有一定的参考价值。

  上午在打zroi的比赛,然而菜得只会T1,虽然是50分的O(n2)写法,大概就是维护一个前缀和,后缀max以及max值,这三个都是用n2的时间进行更新的,最后求值的时候也是n2的,好像线段树维护一下就可以AC了,不是很清楚,出了成绩再说吧

  下午打了打cp的比赛,发现自己什么都不会,弃疗之后手玩提答,AC之后就没时间了

  晚上继续学splay,终于敲出来了splay版的普通平衡树,过程中模板敲错n次,真实彩笔

  这里给出详细注释的板子:

技术分享图片
  1 //普通平衡树
  2 #include<iostream>
  3 #include<cstdio>
  4 #include<cstring>
  5 #include<cstdlib>
  6 #include<cctype>
  7 #include<algorithm>
  8 using namespace std;
  9 int root=0,len=0,n;
 10 struct node{
 11     int v,size,weight,son[2],f;
 12 }tree[100010];
 13 
 14 inline void maintain(int pos)
 15 {tree[pos].size=tree[tree[pos].son[0]].size+tree[tree[pos].son[1]].size+tree[pos].weight;}//重新计算weight
 16 
 17 inline int relation(int pos)
 18 {return (pos==tree[tree[pos].f].son[0])?    0:1;}//判断当前节点与父节点之间的关系
 19 
 20 inline void ins(int x,int y,int z)//在x下面插入y,flag值为z(=1为右儿子,=2为左儿子)
 21 {tree[x].son[z]=y;tree[y].f=x;}
 22 
 23 inline void rotate(int pos){//旋转
 24     int f=tree[pos].f,flag=relation(pos);
 25     ins(tree[f].f,pos,relation(f));//将pos作为f的父亲的儿子插入,与f原位置相同
 26     ins(f,tree[pos].son[flag^1],flag);//将原pos的flag^1儿子作为pos的儿子,与pos原位置相同
 27     ins(pos,f,flag^1);//将f作为pos的儿子插入,flag值为flag^1
 28     maintain(f);    maintain(pos);//重新计算f和pos的size(旋转过程中只有pos和f的size发生了变化)
 29     if (!tree[pos].f)    root=pos;//判断pos是否为根节点
 30 }
 31 
 32 void splay(int pos,int target=0){//pos为要旋转到根的节点,target表示在哪个节点的子树中进行splay操作
 33     while (tree[pos].f!=target){
 34         if (tree[tree[pos].f].f==target)    rotate(pos);//不需要双旋时
 35         else if (relation(pos)==relation(tree[pos].f)){//成直链时先旋父节点再选当前节点
 36             rotate(tree[pos].f);    rotate(pos);
 37         }
 38         else{//不成直链时对当前节点旋转两次
 39             rotate(pos);    rotate(pos);
 40         }
 41     }
 42 }
 43 
 44 int pre(int v){//查询v的前驱并splay到根
 45     int ans,pos=root;//ans为要求的前驱,pos为当前位置,当pos不存在时,查找结束
 46     while (pos){
 47         if (tree[pos].v>=v)    pos=tree[pos].son[0];//当前节点不小于v,在左子树中进行查找
 48         else{
 49             ans=pos;    pos=tree[pos].son[1];//当前位置为新的最优解,对ans进行更新,同时在右子树中进行查找
 50         }
 51     }
 52     splay(ans);//将目的节点旋转到根
 53     return root;
 54 }
 55 
 56 int succ(int v){
 57     int ans,pos=root;
 58     while (pos){
 59         if (tree[pos].v<=v)    pos=tree[pos].son[1];
 60         else{
 61             ans=pos;    pos=tree[pos].son[0];
 62         }
 63     }
 64     splay(ans);
 65     return root;
 66 }
 67 
 68 
 69 int find(int v){//查找值为v的节点
 70     int pos=root;
 71     while (pos&&tree[pos].v!=v){
 72         if (v<tree[pos].v)    pos=tree[pos].son[0];
 73         else    pos=tree[pos].son[1];
 74     }
 75     if (pos)    splay(pos);//如果这个节点存在,对其进行splay操作
 76     return root;
 77 }
 78 
 79 void del(int v){//删除一个值为v的节点
 80     int pos=find(v);
 81     if (tree[pos].weight>1){//值为v的节点不止一个,只需减少节点的weight和size即可(节点已旋转到根)
 82         tree[pos].size--;tree[pos].weight--;return;
 83     }
 84     int s,p;//s为后继,p为前驱
 85     s=succ(v);p=pre(v);
 86     splay(s,p);//p为根节点,将s splay到p的右儿子,此时pos在s的左儿子处,只需要修改pos,s,p三点即可
 87     tree[s].son[0]=0;    tree[s].size--;    tree[p].size--;
 88 }
 89 
 90 int insert(int v){//插入值为v的节点
 91     int pos=root,last=0;
 92     while (pos&&tree[pos].v!=v){//查找过程更新路径上的size
 93         tree[pos].size++;
 94         last=pos;
 95         if (v<tree[pos].v)    pos=tree[pos].son[0];
 96         else    pos=tree[pos].son[1];
 97     }
 98     if (pos){//该节点已存在
 99         tree[pos].size++;    tree[pos].weight++;
100     }
101     else{//该节点不存在,新建节点
102         tree[pos=++len].v=v;    tree[pos].son[0]=tree[pos].son[1]=0;    tree[pos].size=tree[pos].weight=1;
103         tree[pos].f=last;    tree[last].son[(v<tree[last].v)?0:1]=pos;
104     }
105     splay(pos);//将该节点splay到根
106     return root;
107 }
108 
109 int rank(int v){//查找v的排名
110     int pos=find(v);
111     if (!pos){//该节点不存在,新建节点,获取排名后删去
112         pos=insert(v);
113         int ans=tree[tree[pos].son[0]].size;//当前节点已旋转到根,其排名即为左子树的size值
114         del(v);
115         return ans;
116     }
117     return tree[tree[pos].son[0]].size;//当前节点已旋转到根,其排名即为左子树的size值
118 }
119 
120 int kth(int k){//查找排名为k的值,方式与find相同
121     int pos=root,sz;
122     sz=tree[tree[pos].son[0]].size;
123     while (k<sz||k>=sz+tree[pos].weight){
124         if (k<sz)    pos=tree[pos].son[0];
125         else{
126             k-=sz+tree[pos].weight;    pos=tree[pos].son[1];
127         }
128         sz=tree[tree[pos].son[0]].size;
129     }
130     splay(pos);
131     return tree[pos].v;
132 }
133 
134 char buf[1<<15],*fs,*ft;
135 inline char getc(){return (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),fs==ft))?0:*fs++;}
136 
137 int read(){
138     int x=0,y=1;char ch=getc();
139     while (!isdigit(ch)){if (ch==-)y=-1;ch=getc();}
140     while (isdigit(ch)){x=(x<<1)+(x<<3)+ch-0;ch=getc();}
141     return x*y;
142 }
143 
144 void put(int x){
145     if (x==0){putchar(0);putchar(\n);return;}
146     if (x<0){putchar(-);x=-x;}
147     char ch[15];int top=0;
148     while (x){ch[++top]=x%10+0;x/=10;}
149     while (top)    putchar(ch[top--]);
150     putchar(\n);
151 }
152 
153 int main(){
154     n=read();
155     //插入max和min节点,防止出现删除过程中前驱后继不存在的情况
156     insert(0x7fffffff);
157     root=1;
158     insert(0x80000000);
159     while (n--){
160         int opt,x;
161         opt=read();x=read();
162         if (opt==1)    insert(x);
163         else if (opt==2)    del(x);
164         else if (opt==3)    put(rank(x));//因为左子树中存在min节点,因此只输出左子树的size值即可
165         else if (opt==4)    put(kth(x));
166         else if (opt==5)    put(tree[pre(x)].v);
167         else if (opt==6)    put(tree[succ(x)].v);
168     }
169     return 0;
170 }
splay(普通平衡树)

 

以上是关于日总结——20180303的主要内容,如果未能解决你的问题,请参考以下文章

Knowledge Point 20180303 对比编译器解释器与Javac编译原理

Linux学习之路-虚拟化介绍20180303

Knowledge Point 20180303 详解main函数

;~ 小部分AutoHotkey源代码片段测试模板2019年10月9日.ahk

python常用代码片段总结

BootStrap有用代码片段(持续总结)