这是两个月前写的,看能不能搬运过来……

动态树是一类维护森林连通性的问题(已纠正,感谢ZQC巨佬),目前最(wo)常(zhi)见(hui)的动态树就是LCT(Link-Cut-Tree),然而LCT似乎是处理路径的,处理子树可能力不足。据说有一种称为Top Tree数据结构,可以处理所有。但是学不动了Orz
LCT中最主要的是Access操作,Access(u)操作的含义是,从当前的节点u向他所在的根节点连一条重路径,这是相当于把沿路的重路径全都断开,重新拉一条从u到根的重路径。
makeroot(x)操作:
若想让u成为当前树的根节点,则可以先access(u),再splay(u),把u转为当前splay的根节点。因为splay维护的是深度,所以u没有右儿子(没有比u还要深的点,因为重链定义),所以换根就相当于一次区间翻转,交换左右子树即完成区间翻转。此时就可以打标记了。
所以,makeroot=access+splay+rev
还有一个isroot操作,超级简单,就是判断这是不是一条重路径的根,只要他的fa指针指向的节点的左右子树都不是他(证明此时这是一条虚边),那么这就是一棵子树的根节点。
link(x,y)操作:
在u和v之间连边,可以makeroot(u),再让u的父亲为v,这就相当于v本身是一棵splay,而u和v之间连了条轻边。
cut(u,v)操作:
断开u和v之间的边,可以先makeroot(u),再access(v),再splay(v),此时v的左儿子必定为u,于是断开v和v的左儿子即可。
至于翻转标记的传递,就是跟Splay一样就行了。
但标记下放有一个问题。因为splay是时时刻刻在分裂与合并的,因为要动态维护每条重链,所以在splay之前,要先把根节点到当前节点全部下放一遍标记,防止标记下放不完全。
split(x,y)操作:
split相当于把两个子树分开,考虑到我们cut的时候第一步也是分开,所以

$split=makeroot(u)+access(v)+splay(v)$
然后还要保存一些轻边(虚边),对于轻边我们需要单独记录处理。在原树上,当前重链的顶端节点与他的父亲的边即为轻边,如果不记录,树将是不完整的。
具体到代码实现,可以是当前splay的根节点的父亲即为当前splay上面的那个重链所在的splay上的点,但上面的splay的儿子并不指向当前splay的父亲,即为用splay的根节点的父亲来存储轻边。
动态树的主要时间消耗在Access上,而Access的时间复杂度是

$O(nlogn)$
好像最后在UOJ群里看到一句话:
*树剖能做的,动态树都能做,只不过有的东西动态树做起来比树剖烦的多*
好像超级有道理,因为我写的维护子树size,树剖的话天生自带,但是LCT每次Access跳轻重边的时候都要交换,超级烦。
下面是这几天做的一点题目:
1.洞穴勘测
裸的连通性询问。

 #include<bits/stdc++.h>
#define N 10005
#define inf 1000000007
using namespace std;
int n,m;
struct Link_Cut_Tree{
int fa[N],c[N][],q[N],top;bool rev[N];
Link_Cut_Tree(){
top=;memset(fa,,sizeof(fa));
memset(c,,sizeof(c));
memset(rev,,sizeof(rev));
}
inline bool isroot(int x){return c[fa[x]][]!=x&&c[fa[x]][]!=x;}
inline void pushdown(int x){
int l=c[x][],r=c[x][];
if(rev[x]){
rev[x]^=;rev[l]^=;rev[r]^=;
swap(c[x][],c[x][]);
}
}
void rotate(int x){
int y=fa[x],z=fa[y],l,r;
l=(c[y][]==x);r=l^;
if(!isroot(y))c[z][c[z][]==y]=x;
fa[c[x][r]]=y;fa[y]=x;fa[x]=z;
c[y][l]=c[x][r];c[x][r]=y;
}
void splay(int x){
int top=;q[++top]=x;
for(int i=x;!isroot(i);i=fa[i])q[++top]=fa[i];
while(top)pushdown(q[top--]);
while(!isroot(x)){
int y=fa[x],z=fa[y];
if(!isroot(y)){
if(c[y][]==x^c[z][]==y)rotate(x);else rotate(y);
}
rotate(x);
}
}
void access(int x){for(int t=;x;t=x,x=fa[x])splay(x),c[x][]=t;}
void makeroot(int x){access(x);splay(x);rev[x]^=;}
void link(int x,int y){makeroot(x);fa[x]=y;splay(x);}
void split(int x,int y){makeroot(x);access(y);splay(y);}
void cut(int x,int y){split(x,y);c[y][]=fa[x]=;}
int find(int x){
access(x);splay(x);int y=x;while(c[y][])y=c[y][];return y;
}
}T;
inline int read(){
int x=,f=;char ch;
do{ch=getchar();if(ch=='-')f=-;}while(ch<''||ch>'');
do{x=x*+ch-'';ch=getchar();}while(ch>=''&&ch<='');
return f*x;
}
int main(){
char s[];int x,y;
n=read();m=read();
for(int i=;i<=m;i++){
scanf("%s",s);
x=read();y=read();
if(s[]=='C')T.link(x,y);
if(s[]=='D')T.cut(x,y);
if(s[]=='Q'){
int xx=T.find(x),yy=T.find(y);
if(xx==yy)puts("Yes");else puts("No");
}
}
return ;
}

2.bzoj1180 OTOCI
修改,连边,区间权值合。
其实可以先读入所有的边得到最后的树,然后离线树剖,用并查集维护边就行了
本蒟蒻还是写了Link-Cut-Tree

 #include<bits/stdc++.h>
#define N 30005
#define inf 1000000000
#define yql 1000000007
#define ll long long
using namespace std;
int q,n;
struct Link_Cut_Tree{
int c[N][],fa[N],sumv[N],val[N],q[N],top[N];
bool rev[N];
void pushup(int x){
int l=c[x][],r=c[x][];sumv[x]=sumv[l]+sumv[r]+val[x];
}
void pushdown(int x){
int l=c[x][],r=c[x][];
if(rev[x]){
rev[x]^=;rev[r]^=;rev[l]^=;
swap(c[x][],c[x][]);
}
}
bool isroot(int x){return c[fa[x]][]!=x&&c[fa[x]][]!=x;}
void rotate(int x){
int y=fa[x],z=fa[y],l,r;
l=(c[y][]==x);r=l^;
if(!isroot(y))c[z][c[z][]==y]=x;
fa[c[x][r]]=y;fa[y]=x;fa[x]=z;
c[y][l]=c[x][r];c[x][r]=y;
pushup(y);pushup(x);
}
void splay(int x){
int top=;q[++top]=x;
for(int i=x;!isroot(i);i=fa[i])q[++top]=fa[i];
while(top)pushdown(q[top--]);
while(!isroot(x)){
int y=fa[x],z=fa[y];
if(!isroot(y)){
if(c[y][]==x^c[z][]==y)rotate(x);else rotate(y);
}
rotate(x);
}
}
void access(int x){for(int t=;x;t=x,x=fa[x])splay(x),c[x][]=t,pushup(x);}
void makeroot(int x){access(x);splay(x);rev[x]^=;}
void link(int x,int y){makeroot(x);fa[x]=y;}
void split(int x,int y){makeroot(x);access(y);splay(y);}
void cut(int x,int y){split(x,y);c[y][]=fa[x]=;}
int find(int x){
access(x);splay(x);int y=x;while(c[y][])y=c[y][];return y;
}
}T;
inline int read(){
int f=,x=;char ch;
do{ch=getchar();if(ch=='-')f=-;}while(ch<''||ch>'');
do{x=x*+ch-'';ch=getchar();}while(ch>=''&&ch<='');
return f*x;
}
int main(){
n=read();
for(int i=;i<=n;i++){T.sumv[i]=read();T.val[i]=T.sumv[i];}
q=read();char s[];
while(q--){
scanf("%s",s);int x=read(),y=read();
if(s[]=='b'){
int xx=T.find(x),yy=T.find(y);
if(xx==yy)puts("no");
else puts("yes"),T.link(x,y);
}
if(s[]=='p')T.makeroot(x),T.val[x]=y,T.pushup(x);
if(s[]=='e'){
int xx=T.find(x),yy=T.find(y);
if(xx!=yy)puts("impossible");
else{
T.makeroot(x);T.access(y);T.splay(y);
printf("%d\n",T.sumv[y]);
}
}
}
return ;
}

3.NOI2014 膜法森林
考虑Kruskal求出最小生成树,每次加,如果当前的边成环,那么就在之前的边里找一个最大权的cut掉。
维护连通性,cut边,最大值询问,LCT很擅长啦~

 #include<bits/stdc++.h>
#define inf 1000000007
#define N 200005
using namespace std;
int n,m,cnt,_=inf;
int f[N];
int find(int x){return x==f[x]?x:f[x]=find(f[x]);}
struct Edge{
int u,v,w,c;
bool operator<(const Edge &x)const{return w<x.w;}
}G[*N]; struct Link_Cut_Tree{
int c[N][],fa[N],q[N],rev[N],top;
int maxv[N],val[N];
inline void pushup(int x){
int l=c[x][],r=c[x][];
maxv[x]=x;
if(val[maxv[l]]>val[maxv[x]])maxv[x]=maxv[l];
if(val[maxv[r]]>val[maxv[x]])maxv[x]=maxv[r];
}
Link_Cut_Tree(){top=;memset(rev,,sizeof(rev));}
bool isroot(int x){return c[fa[x]][]!=x&&c[fa[x]][]!=x;}
void pushdown(int x){
int l=c[x][],r=c[x][];
if(rev[x]){
rev[l]^=;rev[r]^=;rev[x]^=;
swap(c[x][],c[x][]);
}
}
void rotate(int x){
int y=fa[x],z=fa[y],l,r;
l=(c[y][])==x;r=l^;
if(!isroot(y))c[z][c[z][]==y]=x;
fa[c[x][r]]=y;fa[y]=x;fa[x]=z;
c[y][l]=c[x][r];c[x][r]=y;
pushup(y);pushup(x);
}
void splay(int x){
int top=;q[++top]=x;
for(int i=x;!isroot(i);i=fa[i])q[++top]=fa[i];
while(top)pushdown(q[top--]);
while(!isroot(x)){
int y=fa[x],z=fa[y];
if(!isroot(y)){
if(c[y][]==x^c[z][]==y)rotate(x);else rotate(y);
}
rotate(x);
}
}
void access(int x){for(int t=;x;t=x,x=fa[x])splay(x),c[x][]=t,pushup(x);}
void makeroot(int x){access(x);splay(x);rev[x]^=;}
void link(int x,int y){makeroot(x);fa[x]=y;splay(x);}
void split(int x,int y){makeroot(x);access(y);splay(y);}
void cut(int x,int y){split(x,y);c[y][]=fa[x]=;pushup(y);}
int find(int x){access(x);splay(x);int y=x;while(c[y][])y=c[y][];return y;}
int querymax(int x,int y){split(x,y);return maxv[y];}
};
Link_Cut_Tree T;
inline int read(){
int f=,x=;char ch;
do{ch=getchar();if(ch=='')f=-;}while(ch<''||ch>'');
do{x=x*+ch-'';ch=getchar();}while(ch>=''&&ch<='');
return f*x;
}
int main(){
n=read();m=read();
for(int i=;i<=n+;i++)f[i]=i;
for(int i=;i<=m;i++){
G[i].u=read(),G[i].v=read(),G[i].w=read();G[i].c=read();
}
sort(G+,G+m+);
int tot=;
for(int i=;i<=m;i++){
int u=G[i].u,v=G[i].v,w=G[i].w,c=G[i].c;
if(find(u)==find(v)){
int t=T.querymax(u,v);
if(T.val[t]>G[i].c){
T.cut(t,G[t-n].u);
T.cut(t,G[t-n].v);
}
else {
if(find()==find(n))_=min(_,G[i].w+T.val[T.querymax(,n)]);
continue;
}
}
else f[find(u)]=find(v);
T.val[n+i]=G[i].c;T.maxv[n+i]=n+i;
T.link(u,n+i);T.link(v,n+i);
if(find()==find(n))_=min(_,G[i].w+T.val[T.querymax(,n)]);
}
if(_==inf)puts("-1");else printf("%d\n",_);
return ;
}

4.uoj 共价大爷游长沙
%%%%毛爷爷,不看题解不会系列。
这题做的极其艰辛:
1.zcy:我怎么维护子树size啊…………啊………………
想了半个下午,我好像会了!去机房写!
2.zcy:我的权值怎么这么小啊,都是几十几十的东西……
wori,随机数种子选的有毒?我去uoj上找一个吧……
3.zcy:我的link怎么权值改的那么鬼啊?我看看……
wori,cut写错了,mdzz。
代码准确度啊……

#include<bits/stdc++.h>
#define N 300100
using namespace std;
int n,m,x,y,z;
struct Link_Cut_Tree{
int c[N][],q[N],fa[N],size[N],top,rev[N],val[N],sumv[N];
int a[N],b[N],w[N],sum;
inline bool isroot(int x){return fa[x]==||c[fa[x]][]!=x&&c[fa[x]][]!=x;}
inline void pushdown(int x){
int l=c[x][],r=c[x][];
if(rev[x]){
rev[l]^=;rev[r]^=;rev[x]^=;
swap(c[x][],c[x][]);
}
}
void pushall(int x){
if(!isroot(x))pushall(fa[x]);pushdown(x);
}
inline void pushup(int x){
sumv[x] = val[x]^sumv[c[x][]]^sumv[c[x][]];
}
void rotate(int x){
int y = fa[x],g=fa[y],ch=c[y][]==x;
if (!isroot(y))c[g][c[g][]==y]=x;
c[y][ch]=c[x][!ch],fa[c[y][ch]]=y;
fa[y] =x,fa[x]=g,c[x][!ch] = y;
pushup(y);
}
void splay(int x){
int top=;q[++top]=x;
for(int i=x;!isroot(i);i=fa[i])q[++top]=fa[i];
while(top)pushdown(q[top--]);
while(!isroot(x)){
int y=fa[x],z=fa[y];
if(!isroot(y)){
if(c[y][]==x^c[z][]==y)rotate(x);else rotate(y);
}
rotate(x);
}
pushup(x);
}
void access(int x){
for(int t=;x;t=x,x=fa[x]){
splay(x);val[x]^=sumv[t]^sumv[c[x][]];
c[x][]=t;pushup(x);
}
}
void makeroot(int x){access(x);splay(x);rev[x]^=;}
void link(int x,int y){
makeroot(x);makeroot(y);fa[x]=y;val[y]^=sumv[x];pushup(y);
}
void split(int x,int y){makeroot(x);access(y);splay(y);}
void cut(int x,int y){
makeroot(y);access(y);splay(x);fa[x]=;val[y]^=sumv[x];pushup(y);
}
void change(int x,int v){access(x);splay(x);val[x]^=v;pushup(x);}
}T; struct Edge{
int u;int v;int w;
Edge(int a=,int b=,int c=){u=a;v=b;w=c;}
}G[*N];
inline int read(){
int x=,f=;char ch;
do{ch=getchar();if(ch=='-')f=-;}while(ch<''||ch>'');
do{x=x*+ch-'';ch=getchar();}while(ch>=''&&ch<='');
return f*x;
}
int main(){
int id;
id=read();n=read();m=read();
srand(time(NULL));
for(int i=;i<n;i++){
x=read(),y=read();
T.link(x,y);
}x=;y=;
int tot=,res=;
while(m--){
int opt=read(),x,y,u,v;
if(opt==){
x=read();y=read();u=read();v=read();
T.cut(x,y);T.link(u,v);//printf("%d\n",T.val[v]);
}
else if(opt==){
int k=rand();
x=read(),y=read();while(!k)k=rand();
G[++tot]=Edge(x,y,k);res^=k;
T.change(x,k);T.change(y,k);
//printf("%d\n",T.val[y]);
}
else if(opt==){
x=read();
res^=G[x].w;
T.change(G[x].u,G[x].w);T.change(G[x].v,G[x].w);
}
else if(opt==){
x=read();y=read();
T.makeroot(x);T.access(y);
if(T.val[y]==res)puts("YES");
else puts("NO");
}
//printf("%d\n",res);printf("%d\n",T.val[y]);
}
return ;
}

不开心,这个快把我写死的LCT居然只有100行
5.ZJOI2012 网络
这题如果单看每种颜色,我们只要建一个LCT就能轻松水过去,无非是要加个cnt
但是颜色多怎么办?考虑颜色种类很小,我们多建几个LCT不就行了么?

 #include<bits/stdc++.h>
#define N 10005
#define M 100005
using namespace std;
int n, m, c, k, u, v, w, op, x,val[N];
struct Link_Cut_Tree{
int c[N][],fa[N],rev[N],maxv[N],cnt[N],q[N];
inline void pushup(int x){
maxv[x]=val[x];int l=c[x][],r=c[x][];
if(l)maxv[x]=max(maxv[x],maxv[l]);
if(r)maxv[x]=max(maxv[x],maxv[r]);
}
inline void pushdown(int x){
int l=c[x][],r=c[x][];
if(rev[x]){
rev[l]^=;rev[r]^=;rev[x]^=;
swap(c[x][],c[x][]);
}
}
bool isroot(int x){return c[fa[x]][]!=x&&c[fa[x]][]!=x;}
void rotate(int x){
int y=fa[x],z=fa[y],l,r;
l=(c[y][])==x;r=l^;
if(!isroot(y))c[z][c[z][]==y]=x;
fa[c[x][r]]=y;fa[y]=x;fa[x]=z;
c[y][l]=c[x][r];c[x][r]=y;
pushup(y);pushup(x);
}
void splay(int x){
int top=;q[++top]=x;
for(int i=x;!isroot(i);i=fa[i])q[++top]=fa[i];
while(top)pushdown(q[top--]);
while(!isroot(x)){
int y=fa[x],z=fa[y];
if(!isroot(y)){
if(c[y][]==x^c[z][]==y)rotate(x);else rotate(y);
}
rotate(x);
}
}
void access(int x){for(int t=;x;t=x,x=fa[x])splay(x),c[x][]=t,pushup(x);}
void makeroot(int x){access(x);splay(x);rev[x]^=;}
void link(int x,int y){cnt[x]++;cnt[y]++;makeroot(x);fa[x]=y;splay(x);}
void split(int x,int y){makeroot(x);access(y);splay(y);}
void cut(int x,int y){split(x,y);cnt[x]--;cnt[y]--;c[y][]=fa[x]=;pushup(y);}
int find(int x){access(x);splay(x);int y=x;while(c[y][])y=c[y][];return y;}
int querymax(int x,int y){split(x,y);return maxv[y];}
}lct[];
inline int read(){
int f=,x=;char ch;
do{ch=getchar();if(ch=='')f=-;}while(ch<''||ch>'');
do{x=x*+ch-'';ch=getchar();}while(ch>=''&&ch<='');
return f*x;
}
struct Edge{
int u,v;
bool operator<(const Edge &x)const{if(u!=x.u)return u<x.u;
else return v<x.v;}
};
map<Edge,int> mp;
int main(){
n=read();m=read();c=read();k=read();
for(int i=;i<=n;i++)val[i]=read();
for(int i=;i<=m;i++){
int u=read(),v=read(),w=read();
w++;
Edge e1=(Edge){u,v},e2=(Edge){v,u};
mp[e1]=mp[e2]=w;
lct[w].link(u,v);
}
while(k--){
int opt=read();
if(opt==){
int x=read(),w=read();
val[x]=w;
for(int i=;i<=c;i++)lct[i].splay(x);
}
else if(opt==){
int u=read(),v=read(),w=read();
w++;
Edge a=(Edge){u,v},b=(Edge){v,u};
if(!mp.count(a)){
puts("No such edge.");continue;
}
int xxx=mp[a];
if(xxx==w){
puts("Success.");continue;
}
if(lct[w].cnt[u]>=||lct[w].cnt[v]>=){
puts("Error 1.");continue;
}
if(lct[w].find(u)==lct[w].find(v)){
puts("Error 2.");continue;
}
puts("Success.");
lct[xxx].cut(u,v);lct[w].link(u,v);
mp[a]=mp[b]=w;
}else{
int w=read(),u=read(),v=read();
w++;
if(lct[w].find(u)!=lct[w].find(v)){
puts("-1");continue;
}
printf("%d\n",lct[w].querymax(u,v));
}
}
return ;
}

【学习笔记】动态树Link-Cut-Tree的更多相关文章

  1. 动态树(Link Cut Tree) :SPOJ 375 Query on a tree

    QTREE - Query on a tree #number-theory You are given a tree (an acyclic undirected connected graph) ...

  2. 【学习笔记】LCT link cut tree

    大概就是供自己复习的吧 1. 细节讲解 安利两篇blog: Menci 非常好的讲解与题单 2.模板 把 $ rev $ 和 $ pushdown $ 的位置记清 #define lc son[x][ ...

  3. 学习笔记-动态树Link-Cut-Tree

    --少年你有梦想吗? --少年你听说过安利吗? 安利一个集训队讲解:http://wenku.baidu.com/view/75906f160b4e767f5acfcedb 关于动态树问题,有多种方法 ...

  4. LCT总结——概念篇+洛谷P3690[模板]Link Cut Tree(动态树)(LCT,Splay)

    为了优化体验(其实是强迫症),蒟蒻把总结拆成了两篇,方便不同学习阶段的Dalao们切换. LCT总结--应用篇戳这里 概念.性质简述 首先介绍一下链剖分的概念(感谢laofu的讲课) 链剖分,是指一类 ...

  5. Link Cut Tree学习笔记

    从这里开始 动态树问题和Link Cut Tree 一些定义 access操作 换根操作 link和cut操作 时间复杂度证明 Link Cut Tree维护链上信息 Link Cut Tree维护子 ...

  6. P3690 【模板】Link Cut Tree (动态树)

    P3690 [模板]Link Cut Tree (动态树) 认父不认子的lct 注意:不 要 把 $fa[x]$和$nrt(x)$ 混 在 一 起 ! #include<cstdio> v ...

  7. 【刷题】洛谷 P3690 【模板】Link Cut Tree (动态树)

    题目背景 动态树 题目描述 给定n个点以及每个点的权值,要你处理接下来的m个操作.操作有4种.操作从0到3编号.点从1到n编号. 0:后接两个整数(x,y),代表询问从x到y的路径上的点的权值的xor ...

  8. LuoguP3690 【模板】Link Cut Tree (动态树) LCT模板

    P3690 [模板]Link Cut Tree (动态树) 题目背景 动态树 题目描述 给定n个点以及每个点的权值,要你处理接下来的m个操作.操作有4种.操作从0到3编号.点从1到n编号. 0:后接两 ...

  9. 学习笔记:Link Cut Tree

    模板题 原理 类似树链剖分对重儿子/长儿子剖分,Link Cut Tree 也做的是类似的链剖分. 每个节点选出 \(0 / 1\) 个儿子作为实儿子,剩下是虚儿子.对应的边是实边/虚边,虚实时可以进 ...

  10. LG3690 【模板】Link Cut Tree (动态树)

    题意 给定n个点以及每个点的权值,要你处理接下来的m个操作.操作有4种.操作从0到3编号.点从1到n编号. 0:后接两个整数(x,y),代表询问从x到y的路径上的点的权值的xor和.保证x到y是联通的 ...

随机推荐

  1. 【bzoj3297】[USACO2011 Open]forgot STL+dp

    题目描述 发生了这么多,贝茜已经忘记了她cowtube密码.然而,她记得一些有用的信息. 首先,她记得她的密码(记为变量P)长度为L(1 <= L<=1,000)字符串,并可以被分成 一个 ...

  2. 《转》HTTP 协议入门

    HTTP 协议是互联网的基础协议,也是网页开发的必备知识,最新版本 HTTP/2 更是让它成为技术热点. 本文介绍 HTTP 协议的历史演变和设计思路. 一.HTTP/0.9 HTTP 是基于 TCP ...

  3. Socket_SSH-3(粘包)

    粘包:两次数据粘到一起了.在Windows中基本看不出来效果. 服务器端的配置: import socket,os,time server=socket.socket() server.bind((' ...

  4. BZOJ1031:[JSOI2007]字符加密——题解

    http://www.lydsy.com/JudgeOnline/problem.php?id=1031 喜欢钻研问题的JS同学,最近又迷上了对加密方法的思考.一天,他突然想出了一种他认为是终极的加密 ...

  5. 字符串构造的dp 【bzoj1009 &bzoj1030】

    1009: [HNOI2008]GT考试 Time Limit: 1 Sec  Memory Limit: 162 MB Submit: 4305  Solved: 2637 [Submit][Sta ...

  6. sass的颜色函数

    sass中有些非常实用的颜色处理函数,总结如下 1.颜色加深或变浅 lighten($color,$amount) //颜色变浅 darken($color,$amount) //颜色加深 例如: l ...

  7. SRM13 T3 花六游鸟小(结论题)

    哇这题是真的喵,HR智商太高辣 这题的难点就是看了题解之后怎么证明题解里的结论... 结论①:深度大于logm的点肯定能达到最大值 证明:显然一个西瓜的属性里0数量一半1数量一半我们取到的1数量最少, ...

  8. 【贪心/DP/单调队列】【CF1029B】Creating the Contest

    Description 给你一个单调不下降的长度为n的序列,请你找出一个最长的子序列,满足找出的子序列中,\(A_i<=A_{i-1}~\times~2\),其中i为下标,A为找出的子序列.对于 ...

  9. 第三方库安装——requests

    环境 操作系统:CentOS 6.7 32-bit Python:2.6.6 安装 pip install requests

  10. Rectangle 暴力枚举大法

    frog has a piece of paper divided into n rows and m columns. Today, she would like to draw a rectang ...