楼教主男人八题之一。
点分治看腻了吧。来点新鲜的。
关于启发式合并,我的上篇博客已经写了一些,请移步 这儿。
这题和hdu4812一样,也是询问 是否存在/有多少个/各种最小 满足某条件的树的路径。
树的路径问题在这里可化为树上一对点的问题。
同样,每个叶节点建一个包含自己的平衡树。
dfs回溯时,非叶节点选取含点最多的子节点的平衡树作为自己的平衡树,将其他的子节点的平衡树暴力合并到这个树上。
同时查询这个子节点中小于给定要求长度的节点的个数,更新答案即可。
注意暴力合并时,要先询问再合并,否则本树上的节点会有重复计算。
由于每个节点的插入次数小于O(logn),总插入次数不超过O(nlogn)。
用treap进行插入、查询复杂度为O(logn),因此总复杂度为O(nlognlogn)。
不过不进行删除操作的话,需要O(nlogn)的空间。
实际效果不错,157ms。
#include
#include
#include
#include
using namespace std;
#define NN 10100
int tn;
struct treap{
int l,r,fix,tot,val,cnt;
void init(int v){
l=r=0;
fix=rand()*rand();
tot=cnt=1;
val=v;
}
}t[NN*12];
void init_treap(){
srand(1314);
tn=0;
t[0].cnt=t[0].tot=0;
t[0].fix=-1000001000;
}
#define getot(p) \
do{\
t[p].tot=t[p].cnt;\
if (t[p].l) t[p].tot+=t[t[p].l].tot;\
if (t[p].r) t[p].tot+=t[t[p].r].tot;\
}while(0);
/*
inline void getot(int p){
t[p].tot=t[p].cnt;
if (t[p].l) t[p].tot+=t[t[p].l].tot;
if (t[p].r) t[p].tot+=t[t[p].r].tot;
}
*/
inline void rrot(int &p){
int y=t[p].l;
t[p].l=t[y].r;
t[y].r=p;
getot(p);
p=y;
getot(p);
}
inline void lrot(int &p){
int y=t[p].r;
t[p].r=t[y].l;
t[y].l=p;
getot(p);
p=y;
getot(p);
}
void insert(int val,int &p,int num=1){
if (p==0) {
p=++tn;
t[p].init(val);
t[p].cnt=t[p].tot=num;
return;
}
t[p].tot+=num;
if (val==t[p].val) {t[p].cnt+=num;}
else if (valt[t[p].l].fix) rrot(p);
}
else {
insert(val,t[p].r,num);
if (t[p].fix>t[t[p].r].fix) lrot(p);
}
//getot(p);
}
int queryless(int val,int p){
if (val==t[p].val) return t[t[p].l].tot+t[p].cnt;
else if (valma) {ma=tot[v];son[u]=v;sw[u]=w[e];}
tot[u]+=tot[v];
}
}
}
void merge(int &ru,int rv,int du,int dv){
insert(t[rv].val+dv-du,ru,t[rv].cnt);
if (t[rv].l) merge(ru,t[rv].l,du,dv);
if (t[rv].r) merge(ru,t[rv].r,du,dv);
}
void query(int &ru,int rv,int du,int dv){
int tmp,val;
val=k-t[rv].val-du-dv;
tmp=queryless(val,ru);
ans+=tmp*t[rv].cnt;
if (t[rv].l) query(ru,t[rv].l,du,dv);
if (t[rv].r) query(ru,t[rv].r,du,dv);
}
void dfs2(int u,int fa,int dd){
int e,v;
if (son[u]==-1){
root[u]=++tn;t[tn].init(0);
dis[u]=dd;
return;
}
dfs2(son[u],u,sw[u]);
root[u]=root[son[u]];
dis[u]=dis[son[u]];
ans+=queryless(k-dis[u],root[u]);
insert(-dis[u],root[u],1);
for(e=fi[u];e!=-1;e=ne[e]){
v=to[e];
if (v!=fa&&v!=son[u]){
dfs2(v,u,w[e]);
query(root[u],root[v],dis[u],dis[v]);
merge(root[u],root[v],dis[u],dis[v]);
}
}
dis[u]+=dd;
}
int main(){
//freopen("1741in.txt","r",stdin);
int a,b,c,i;
while(scanf("%d%d",&n,&k)&&(n||k)){
te=0;
memset(fi,-1,sizeof(fi));
for(i=1;i