treap

比较快的非线性筛法

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值