CF372D 翻
my
[[two pointers]] [[LCA]] [[DFS Tour & Euler Tour]] [[map]]
This problem took me three nights.
Calculate the longest length of interval of indices of nodes in a subtree whose size is less than k.
Sol
Binary search, search the answer? every check at most cost \(O(n\log n)\), and all in \(O(n\log^2n)\) .
No, there is simpler solution.
Use two pointers (尺取法 in Chinese).
Then consider how to add and delete an index.
What we need to know is how to calculate the distance from a node to a subtree.(the part of function Cnt)
It's so hard so I thought so long, and got nothing.
Code
#include<bits/stdc++.h>
using namespace std;
const int N=100005,M=200005;
int k,n,a,b;
int t,h[N],nxt[M],to[M];
void add(int u,int v){
nxt[++t]=h[u],h[u]=t,to[t]=v;
nxt[++t]=h[v],h[v]=t,to[t]=u;
}
int cnt,dfn[N],dep[N];
int f[N][20];
void dfs(int u,int fa){
dfn[u]=++cnt;f[u][0]=fa;dep[u]=dep[fa]+1;
for(int i=1;i<=19;i++)f[u][i]=f[f[u][i-1]][i-1];
for(int e=h[u];e;e=nxt[e])if(to[e]!=fa)dfs(to[e],u);
}
map<int,int>ord;
map<int,int>::iterator it;
int sz,ans,dx,dy;
int dis(int x,int y){
dx=dep[x],dy=dep[y];
if(dep[x]<dep[y])swap(x,y);
for(int i=19;i>=0;i--)if(dep[f[x][i]]>=dep[y])x=f[x][i];
if(x==y)return dx+dy-2*dep[x];
for(int i=19;i>=0;i--)if(f[x][i]!=f[y][i])x=f[x][i],y=f[y][i];
return dx+dy-2*(dep[x]-1);
}
int x,y;
int Cnt(int p){
if(ord.size()==1)return dis(p,ord.begin()->second);
it=ord.upper_bound(dfn[p]);
if(it==ord.end()||it==ord.begin()){
x=ord.begin()->second;
y=ord.rbegin()->second;
}
else{
x=it->second;it--;
y=it->second;
}
return (dis(p,x)+dis(p,y)-dis(x,y))/2;
}
void Add(int x){
sz+=Cnt(x);
ord[dfn[x]]=x;
}
void Del(int x){
ord.erase(dfn[x]);
sz-=Cnt(x);
}
int l,r;
int main(){
scanf("%d%d",&n,&k);
for(int i=1;i<n;i++)scanf("%d%d",&a,&b),add(a,b);
dfs(1,0);
for(ord[dfn[1]]=sz=l=ans=1,r=2;r<=n;r++){
for(Add(r);sz>k;Del(l++));
ans=max(ans,r-l+1);
}
printf("%d",ans);
}

浙公网安备 33010602011771号