比较快的非线性筛法
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
总有一个是答案