一看就不会
写了个60分的暴力就走人
最后两分钟想到一个假的正解:换根维护线段树
20200418:从早上9:00写到10:30,发现是有问题的
因为换根时的修改区间在dfs序上,是连续的
但是查询的区间只是编号连续,在dfs序上不一定连续。。。
所以就只有看题解了
题解:
哦,原来还有这种操作,对编号分块,对编号建线段树
好难写啊
看了一下std
4KB
读不下去了
看了一下Master.Yi大佬的代码
2KB
就看他的了
大概阅读了5min
哦哦哦,这不就是点分治套ST表吗
对每一个点分中心维护一个ST表,记录当前点分区域每个点到点分中心的距离
然后把这个点分区域的所有询问直接利用ST表查询
虽然一次查询,有些点不一定可以查询到最有解,但是最后一定是可以找到最优解的
代码:
#include
#include
#include
#include
using namespace std;
inline int gi()
{
char c;int num=0,flg=1;
while((c=getchar())<'0'||c>'9')if(c=='-')flg=-1;
while(c>='0'&&c<='9'){num=num*10+c-48;c=getchar();}
return num*flg;
}
#define N 100005
#define LOG 18
int n,m,siz[N],stk[N],top,dis[N],st[N][LOG+2],lg[N],ans[N];
bool vis[N];
int fir[N],nxt[N<<1],to[N<<1],cd[N<<1],tot;
inline void adde(int x,int y,int z)
{
to[++tot]=y;nxt[tot]=fir[x];fir[x]=tot;cd[tot]=z;
}
struct node{int id,l,r;};
vector Q[N];
void getroot(int u,int ff,int all,int &g)
{
siz[u]=1;bool flg=1;
for(int p=fir[u],v;p;p=nxt[p]){
v=to[p];
if(!vis[v]&&v!=ff){
getroot(v,u,all,g);
siz[u]+=siz[v];
flg&=((siz[v]<<1)<=all);
}
}
if(flg&&((all-siz[u])<<1)<=all)
g=u;
}
void dfs(int u,int ff)
{
stk[++top]=u;
for(int v,p=fir[u];p;p=nxt[p]){
v=to[p];
if(!vis[v]&&v!=ff){
dis[v]=dis[u]+cd[p];
dfs(v,u);
}
}
}
inline int query(int x,int y)
{
int k=lg[y-x+1];
return min(st[x][k],st[y-(1<>1]+1;st[i][0]=dis[stk[i]];}
for(j=1;j<=lg[top];j++)
for(i=1,l=1<>1)][j-1]);
for(int i=1,l,r;i<=top;i++)
for(int j=0,x=stk[i],lim=Q[x].size();j
std:
#include
#include
#include
#include
#include
using namespace std;
#define INF 1<<29
#define N 100010
int n,bel[17][N],Root[17][N];
int head[N],next[N<<1],end[N<<1],len[N<<1];
inline void addedge(int a,int b,int l){
static int q=1;
end[q]=b;
next[q]=head[a];
head[a]=q;
len[q++]=l;
}
inline void make(int a,int b,int l){
addedge(a,b,l);
addedge(b,a,l);
}
#define l(x) S[x].l
#define r(x) S[x].r
struct Node{
int l,r,re;
}S[15000010];
int cnt;
inline void Insert(int&q,int tl,int tr,int ins,int d){
if(!q){
q=++cnt;
S[q].re=d;
}
S[q].re=min(S[q].re,d);
if(tl==tr)
return;
int mid=(tl+tr)>>1;
if(ins<=mid)
Insert(S[q].l,tl,mid,ins,d);
else
Insert(S[q].r,mid+1,tr,ins,d);
}
inline int Query(int q,int tl,int tr,int dl,int dr){
if(!q)
return INF;
if(dl<=tl&&tr<=dr)
return S[q].re;
int mid=(tl+tr)>>1;
if(dr<=mid)
return Query(S[q].l,tl,mid,dl,dr);
else if(dl>mid)
return Query(S[q].r,mid+1,tr,dl,dr);
else
return min(Query(S[q].l,tl,mid,dl,mid),Query(S[q].r,mid+1,tr,mid+1,dr));
}
int q[N],fr,ta;
struct Array{
int re[N],t[N],tclock,init;
Array():tclock(0),init(0){}
inline int operator[](const int&x){
if(t[x]!=tclock)
t[x]=tclock,re[x]=init;
return re[x];
}
inline void modify(int x,int c){
t[x]=tclock;
re[x]=c;
}
}pa;
int seq[N],id;
int size[N],dis[17][N];
bool ban[N];
inline void solve(int x,int dep){
int i,j;
fr=ta=0;
q[ta++]=x;
id=0,seq[++id]=x;
++pa.tclock;
while(fr^ta){
i=q[fr++];
for(j=head[i];j;j=next[j]){
if(pa[i]!=end[j]&&!ban[end[j]]){
pa.modify(end[j],i);
q[ta++]=seq[++id]=end[j];
}
}
}
int Maxsize,real_Root;
for(i=id;i>=1;--i){
size[seq[i]]=1;
for(j=head[seq[i]];j;j=next[j]){
if(end[j]!=pa[seq[i]]&&!ban[end[j]])
size[seq[i]]+=size[end[j]];
}
}
if(size[x]==1){
bel[dep][x]=x;
Insert(Root[dep][x],1,n,x,0);
return;
}
for(i=1;i<=id;++i){
Maxsize=size[x]-size[seq[i]];
for(j=head[seq[i]];j;j=next[j]){
if(end[j]!=pa[seq[i]]&&!ban[end[j]])
Maxsize=max(Maxsize,size[end[j]]);
}
if(Maxsize<=size[x]/2)
real_Root=seq[i];
}
fr=ta=0;
q[ta++]=real_Root;
++pa.tclock;
dis[dep][real_Root]=0;
bel[dep][real_Root]=real_Root;
Insert(Root[dep][real_Root],1,n,real_Root,0);
while(fr^ta){
i=q[fr++];
for(j=head[i];j;j=next[j]){
if(end[j]!=pa[i]&&!ban[end[j]]){
pa.modify(end[j],i);
dis[dep][end[j]]=dis[dep][i]+len[j];
bel[dep][end[j]]=real_Root;
Insert(Root[dep][real_Root],1,n,end[j],dis[dep][end[j]]);
q[ta++]=end[j];
}
}
}
ban[real_Root]=1;
for(j=head[real_Root];j;j=next[j])
if(!ban[end[j]])
solve(end[j],dep+1);
}
int main(){
freopen("tree.in","r",stdin);
freopen("tree.out","w",stdout);
scanf("%d",&n);
register int i;
int a,b,c;
for(i=1;i