# 和Leo一起做爱树上结构的好孩子之点分治 【BZOJ3784】树上路径

### 由于点分治是一个静态算法，所以对于多次点分治只需要做一次哦

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector>
#include<set>
using namespace std;
typedef int INT;
#define int long long

namespace fastIO{
#define BUF_SIZE 100000
#define OUT_SIZE 100000
#define ll long long
bool IOerror=0;
inline char nc(){
static char buf[BUF_SIZE],*p1=buf+BUF_SIZE,*pend=buf+BUF_SIZE;
if (p1==pend){
if (pend==p1){IOerror=1;return -1;}
//{printf("IO error!\n");system("pause");for (;;);exit(0);}
}
return *p1++;
}
inline bool blank(char ch){return ch==' '||ch=='\n'||ch=='\r'||ch=='\t';}
inline void read(ll &x){
bool sign=0; char ch=nc(); x=0;
for (;blank(ch);ch=nc());
if (IOerror)return;
if (ch=='-')sign=1,ch=nc();
for (;ch>='0'&&ch<='9';ch=nc())x=x*10+ch-'0';
if (sign)x=-x;
}
inline void read(double &x){
bool sign=0; char ch=nc(); x=0;
for (;blank(ch);ch=nc());
if (IOerror)return;
if (ch=='-')sign=1,ch=nc();
for (;ch>='0'&&ch<='9';ch=nc())x=x*10+ch-'0';
if (ch=='.'){
double tmp=1; ch=nc();
for (;ch>='0'&&ch<='9';ch=nc())tmp/=10.0,x+=tmp*(ch-'0');
}
if (sign)x=-x;
}
inline void read(char *s){
char ch=nc();
for (;blank(ch);ch=nc());
if (IOerror)return;
for (;!blank(ch)&&!IOerror;ch=nc())*s++=ch;
*s=0;
}
inline void read(char &c){
for (c=nc();blank(c);c=nc());
if (IOerror){c=-1;return;}
}
inline void read1(int &x){
char ch;int bo=0;x=0;
for (ch=getchar();ch<'0'||ch>'9';ch=getchar())if (ch=='-')bo=1;
for (;ch>='0'&&ch<='9';x=x*10+ch-'0',ch=getchar());
if (bo)x=-x;
}
inline void read1(double &x){
char ch;int bo=0;x=0;
for (ch=getchar();ch<'0'||ch>'9';ch=getchar())if (ch=='-')bo=1;
for (;ch>='0'&&ch<='9';x=x*10+ch-'0',ch=getchar());
if (ch=='.'){
double tmp=1;
for (ch=getchar();ch>='0'&&ch<='9';tmp/=10.0,x+=tmp*(ch-'0'),ch=getchar());
}
if (bo)x=-x;
}
inline void read1(char *s){
char ch=getchar();
for (;blank(ch);ch=getchar());
for (;!blank(ch);ch=getchar())*s++=ch;
*s=0;
}
inline void read1(char &c){for (c=getchar();blank(c);c=getchar());}
inline void read2(int &x){scanf("%d",&x);}
inline void read2(double &x){scanf("%lf",&x);}
inline void read2(char *s){scanf("%s",s);}
inline void read2(char &c){scanf(" %c",&c);}
inline void readln2(char *s){gets(s);}
//fwrite->write
struct Ostream_fwrite{
char *buf,*p1,*pend;
Ostream_fwrite(){buf=new char[BUF_SIZE];p1=buf;pend=buf+BUF_SIZE;}
void out(char ch){
if (p1==pend){
fwrite(buf,1,BUF_SIZE,stdout);p1=buf;
}
*p1++=ch;
}
void print(int x){
static char s[15],*s1;s1=s;
if (!x)*s1++='0';if (x<0)out('-'),x=-x;
while(x)*s1++=x%10+'0',x/=10;
while(s1--!=s)out(*s1);
}
void println(int x){
static char s[15],*s1;s1=s;
if (!x)*s1++='0';if (x<0)out('-'),x=-x;
while(x)*s1++=x%10+'0',x/=10;
while(s1--!=s)out(*s1); out('\n');
}
void print(double x,int y){
static ll mul[]={1,10,100,1000,10000,100000,1000000,10000000,100000000,
1000000000,10000000000LL,100000000000LL,1000000000000LL,10000000000000LL,
100000000000000LL,1000000000000000LL,10000000000000000LL,100000000000000000LL};
if (x<-1e-12)out('-'),x=-x;x*=mul[y];
ll x1=(ll)floor(x); if (x-floor(x)>=0.5)++x1;
ll x2=x1/mul[y],x3=x1-x2*mul[y]; print(x2);
if (y>0){out('.'); for (size_t i=1;i<y&&x3*mul[i]<mul[y];out('0'),++i); print(x3);}
}
void println(double x,int y){print(x,y);out('\n');}
void print(char *s){while (*s)out(*s++);}
void println(char *s){while (*s)out(*s++);out('\n');}
void flush(){if (p1!=buf){fwrite(buf,1,p1-buf,stdout);p1=buf;}}
~Ostream_fwrite(){flush();}
}Ostream;
inline void print(int x){Ostream.print(x);}
inline void println(int x){Ostream.println(x);}
inline void print(char x){Ostream.out(x);}
inline void println(char x){Ostream.out(x);Ostream.out('\n');}
inline void print(double x,int y){Ostream.print(x,y);}
inline void println(double x,int y){Ostream.println(x,y);}
inline void print(char *s){Ostream.print(s);}
inline void println(char *s){Ostream.println(s);}
inline void println(){Ostream.out('\n');}
inline void flush(){Ostream.flush();}
//puts->write
char Out[OUT_SIZE],*o=Out;
inline void print1(int x){
static char buf[15];
char *p1=buf;if (!x)*p1++='0';if (x<0)*o++='-',x=-x;
while(x)*p1++=x%10+'0',x/=10;
while(p1--!=buf)*o++=*p1;
}
inline void println1(int x){print1(x);*o++='\n';}
inline void print1(char c){*o++=c;}
inline void println1(char c){*o++=c;*o++='\n';}
inline void print1(char *s){while (*s)*o++=*s++;}
inline void println1(char *s){print1(s);*o++='\n';}
inline void println1(){*o++='\n';}
inline void flush1(){if (o!=Out){if (*(o-1)=='\n')*--o=0;puts(Out);}}
struct puts_write{
~puts_write(){flush1();}
}_puts;
inline void print2(int x){printf("%d",x);}
inline void println2(int x){printf("%d\n",x);}
inline void print2(char x){printf("%c",x);}
inline void println2(char x){printf("%c\n",x);}
inline void println2(){printf("\n");}
#undef ll
#undef OUT_SIZE
#undef BUF_SIZE
};
using namespace fastIO;
const int N=1e5+100;
struct Front_star{
int u,v,w,nxt;
}e[N<<2];
int cnt=0;
int first[N];
void add(int u,int v,int w){
++cnt;
e[cnt].u=u;
e[cnt].v=v;
e[cnt].w=w;
e[cnt].nxt=first[u];
first[u]=cnt;
}
//
vector<int> A[N*2];
int ans=0;
int n,m,K;
int All;
int root;
int siz[N];
int vis[N];
int cut[N];
int F[N];
int tot=0;
inline void Get_Root(int u,int fat){
int now=0;
siz[u]=1;
for(int i=first[u];i;i=e[i].nxt){
int v=e[i].v;
if(v==fat||vis[v])continue;
Get_Root(v,u);
siz[u]+=siz[v];
if(now<siz[v])now=siz[v];
}
if(now<All-siz[u])now=All-siz[u];
F[u]=now;
if(F[root]>now)root=u;
}
int deep[N];
int d[N];
int Record[N*3];
inline void Get_Deep(int u,int fat){
A[tot].push_back(d[u]);
for(int i=first[u];i;i=e[i].nxt){
int v=e[i].v;
if(vis[v]||v==fat)continue;
d[v]=d[u]+e[i].w;
Get_Deep(v,u);
}
}
inline int Solve(int u,int dep){
++tot;
int Mx=A[tot].size();
int ret=0;
for(int l=0,r=Mx-1;l<r;){
if(A[tot][l]+A[tot][r]>=K){
ret+=r-l;
--r;
}
else ++l;
}
return ret;
}
inline void DFS(int u){
vis[u]=1;
ans+=Solve(u,0);
for(int i=first[u];i;i=e[i].nxt){
int v=e[i].v;
if(vis[v])continue;
ans-=Solve(v,e[i].w);
All=siz[v];
root=0;
Get_Root(v,0);
DFS(root);
}
}
//
multiset<int> S;
void Solve2(int u,int dep,int flag){
++tot;
int Mx=A[tot].size();
for(int l=0,r=Mx-1;l<r;){
if(A[tot][l]+A[tot][r]>=K){
for(int j=l;j<r;++j){
int len=A[tot][j]+A[tot][r];
if(flag==1)S.insert(len);
else{
S.erase(S.find(len));
}
}
r--;
}
else l++;
}
}
void DFS2(int u){
vis[u]=1;
Solve2(u,0,1);
for(int i=first[u];i;i=e[i].nxt){
int v=e[i].v;
if(vis[v])continue;
Solve2(v,e[i].w,-1);
All=siz[v];
root=0;
Get_Root(v,0);
DFS2(root);
}
}
void Solve3(int u,int dep,int flag){
++tot;
cut[tot]=flag;
d[u]=dep;
Get_Deep(u,0);
sort(A[tot].begin(),A[tot].end());
}
void DFS3(int u){
vis[u]=1;
Solve3(u,0,1);
for(int i=first[u];i;i=e[i].nxt){
int v=e[i].v;
if(vis[v])continue;
Solve3(v,e[i].w,-1);
All=siz[v];
root=0;
Get_Root(v,0);
DFS3(root);
}
}
void Pre(){
tot=0;
All=n;
root=0;
memset(vis,0,sizeof(vis));
Get_Root(1,0);
DFS3(root);
}
void GetAns(int sum){
tot=0;
K=sum;
All=n;
root=0;
memset(vis,0,sizeof(vis));
Get_Root(1,0);
DFS2(root);
}
bool Check(int sum){
int ans=0;
K=sum;
for(int i=1;i<=tot;++i){
int Mx=A[i].size();
int ret=0;
for(int l=0,r=Mx-1;l<r;){
if(A[i][l]+A[i][r]>=K){
ret+=r-l;
--r;
}
else ++l;
}
ans=ans+cut[i]*ret;
}
return ans>=m;
}
//inline bool Check(int sum){
//	tot=0;
//	K=sum;
//	ans=0;
//	memset(vis,0,sizeof(vis));
//	All=n;
//	root=0;
//	Get_Root(1,0);
//	DFS(root);
//	return m<=ans;
//}
INT main(){
//	freopen("test.in","r",stdin);
//	freopen("test.out","w",stdout);
F[0]=1e9+7;
for(int i=1;i<n;++i){
int u,v,w;
}
Pre();
int l=1;
int r=1e12+7;
int sum=1;
while(l<=r){
int mid=(l+r)>>1;
if(Check(mid)){
l=mid+1;
sum=mid;
}
else r=mid-1;
}
GetAns(sum);
multiset<int>::iterator It;
int anscnt=0;
for(It=S.begin();It!=S.end();++It){
Record[++anscnt]=*It;
}
for(int i=m;i>=1;--i)println(Record[i]);
}


posted @ 2018-09-24 16:53  SirLeo_JAM  阅读(38)  评论(0编辑  收藏