treap

11 篇文章 0 订阅

比较快的非线性筛法

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
总有一个是答案

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
这是Treap的代码: ``` #include <bits/stdc++.h> using namespace std; struct Node { int key, priority; Node *left, *right; Node(int key, int priority) : key(key), priority(priority), left(NULL), right(NULL) {} }; struct Treap { Node *root; Treap() : root(NULL) {} void rotateRight(Node *&p) { Node *q = p->left; p->left = q->right; q->right = p; p = q; } void rotateLeft(Node *&p) { Node *q = p->right; p->right = q->left; q->left = p; p = q; } void insert(Node *&p, int key, int priority) { if (p == NULL) { p = new Node(key, priority); return; } if (key < p->key) { insert(p->left, key, priority); if (p->priority < p->left->priority) { rotateRight(p); } } else { insert(p->right, key, priority); if (p->priority < p->right->priority) { rotateLeft(p); } } } void remove(Node *&p, int key) { if (p == NULL) { return; } if (key == p->key) { if (p->left == NULL || p->right == NULL) { Node *q = p; if (p->left == NULL) { p = p->right; } else { p = p->left; } delete q; } else { if (p->left->priority > p->right->priority) { rotateRight(p); remove(p->right, key); } else { rotateLeft(p); remove(p->left, key); } } } else if (key < p->key) { remove(p->left, key); } else { remove(p->right, key); } } bool search(Node *p, int key) { if (p == NULL) { return false; } if (key == p->key) { return true; } if (key < p->key) { return search(p->left, key); } else { return search(p->right, key); } } }; int main() { Treap t; t.insert(t.root, 5, rand()); t.insert(t.root, 3, rand()); t.insert(t.root, 8, rand()); t.insert(t.root, 1, rand()); t.insert(t.root, 4, rand()); t.insert(t.root, 6, rand()); t.insert(t.root, 9, rand());

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值