treap

来源:互联网 发布:linux查看io使用情况 编辑:程序博客网 时间:2024/06/06 17:14

比较快的非线性筛法

for(int a=2;a<=n;a++) for(int b=a+a;b<=n;b++)  not_prime[b]=true;

O(nlogn)

for(int a=2;a<=n;a++)  if(!not_prime[a])    for(int b=a+a;b<=n;b++)      not_prime[b]=true; //true不是质数

O(nloglogn)

读入

输出优化
把所有输出合成一个字符串
1s-》0.8不很明显
5百w+

在algorithm中 y1变量已声明 不能再用!

平衡树

treap:比sbt慢些,比sbt好写 要学
sbt:快,比较好写,功能不太全(正常操作)
rbt:红黑树比sbt还快(stl)死难写
logn

spaly:特别慢,功能最强大,不太好写
logn(实际上根号n)要学

treap(不带旋转)

1.性质

【MARK2】

1.平衡树一定是二叉树
2.左儿子其父亲小,右儿子大:性质(中序遍历是排好序的)(节点确定树就确定)
3.缺点 可能很深,插入代价大—》求平衡—》不同的平衡方法不同的平衡树
4.插入

       4      / \     2   5    / \   1   3       /     2.33《---插入的

5.查询
例如:查询【1,4】
【4】+【2(及其子树)】?????

6.treap=tree+heap
每个节点存两个值(key(大根堆的性质,即比下面的要大),value(原来的12345))
问题求key;–》key=rand()为了保证树深logn

    4   / \  2   5 / \1   3    /  2.33《---插入的  

2.merge(p1,p2) [合并操作]

把p1根和p2根的treap合并为p3根 要求必须p1所有数(value)都小于p2所有数即MAX (p1)<=MIN( p2)

3.split(p,k) [拆分操作]

必须:把p根的树,前K小的树拿出来
拆成两个p1<=p2

4.merge和split如何操作

插入

1 2 3 4 5(s)–>1 2 |3 4 5(m)—>1 2| 2.33 |3 4 5—>1 2 2.33 3 4 5

删除

1 2 3 4 5(s)–>1| 2 |3 4 5(m) –>merge 1 和345–>1 3 4 5

merge实操
【MARK3】
merge(p1,p2)

讨论谁是根
1° p1.key>=p2.key

       p1      /  \ (p1.l)  merge(p1.r,p2)

2° p1.key

              p2             /  \ merge(p2.l,p1) (p2,2) 

return 根节点编号

【mark4】
split(p,k)

求k 从根开始能左就左

if(k<=p.l.size)说明小于k的全在l;
—>split(p.l,k)
return p1 ,p2+p点+p.r
   
if(k==p.l.size+1) 直接断掉p和p.r
  

if(k>=p.l.size)
—->split(p.r , k-p.l.size-1)

20:05 2017/10/29【MARK5】

code

int merge(int p1,int p2){    if (!p1) return p2;    if (!p2) return p1;    int pp=newnode;    if (z[p1].key<z[p2].key)    z[p1].r=merge(z[p1].r,p2);    else    z[p2].l=merge(p1,z[p2].l);    return p1;}//无可持久化
pair<int,int> split(int p,int n)//返回两个数pair{    if (z[z[p].l].size>=n)     {        if (!z[p].l) return make_pair(0,p);//left cild empty        else        {            pair<int,int> px=split(z[p].l,n);            int pl=px.first;            z[pr].l=px.second;            return make_pair(pl,pr);        }    }    else     {        if (z[p].r==0) return make_pair(p,0);        else        {            pair<int,int> px=split(z[p].r,n-z[z[p].l].size-1);            z[pl].r=px.first;            int pr=px.second;            return make_pair(p,pr);        }    }}//无可持久化

【MARK6】
练习 找一个线段树 插入再询问区间和

网站 http://www.yhzq-blog.cc/fhq-treap%E6%80%BB%E7%BB%93/

二分图匹配code

bool dfs(int now){  for (int a=1;a<=m;a++)  if (match[now][a] && !use[a])   {    use[a]=true;    if (!result[a] || dfs(result[a]))     {     result[a]=now;     return true;    }   }  return false;}void xiongyali() {  int ans=0;  for (int a=1;a<=n;a++)  {     memset(use,false,sizeof(use));     if (dfs(a)) ans++;  }}

对于变式题
ans
n-ans
m-ans
n+m-ans
总有一个是答案

原创粉丝点击