题解
一看就不会
写了个60分的暴力就走人
最后两分钟想到一个假的正解:换根维护线段树
20200418:从早上9:00写到10:30,发现是有问题的
因为换根时的修改区间在dfs序上,是连续的
但是查询的区间只是编号连续,在dfs序上不一定连续。。。
所以就只有看题解了
题解:
哦,原来还有这种操作,对编号分块,对编号建线段树
好难写啊
看了一下std
4KB
读不下去了
看了一下Master.Yi大佬的代码
2KB
就看他的了
大概阅读了5min
哦哦哦,这不就是点分治套ST表吗
对每一个点分中心维护一个ST表,记录当前点分区域每个点到点分中心的距离
然后把这个点分区域的所有询问直接利用ST表查询
虽然一次查询,有些点不一定可以查询到最有解,但是最后一定是可以找到最优解的
代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
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<node> 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<<k)+1][k]);
}
void solve(int u)
{
dis[u]=top=0;
dfs(u,0);
sort(stk+1,stk+1+top);
int i,j,l;lg[0]=-1;
for(i=1;i<=top;i++){lg[i]=lg[i>>1]+1;st[i][0]=dis[stk[i]];}
for(j=1;j<=lg[top];j++)
for(i=1,l=1<<j;i+l-1<=top;i++)
st[i][j]=min(st[i][j-1],st[i+(l>>1)][j-1]);
for(int i=1,l,r;i<=top;i++)
for(int j=0,x=stk[i],lim=Q[x].size();j<lim;j++){
l=lower_bound(stk+1,stk+1+top,Q[x][j].l)-stk;
r=upper_bound(stk+1,stk+1+top,Q[x][j].r)-stk-1;
if(l<=r)ans[Q[x][j].id]=min(ans[Q[x][j].id],dis[x]+query(l,r));
}
}
void TDC(int u,int all)
{
getroot(u,0,all,u);vis[u]=1;
solve(u);
for(int i=fir[u],v;i;i=nxt[i])
if(!vis[v=to[i]])
TDC(v,siz[v]<siz[u]?siz[v]:all-siz[u]);
}
int main()
{
freopen("tree.in","r",stdin);
freopen("tree.out","w",stdout);
int i,x,y,z,l,r;
n=gi();
for(i=1;i<n;i++){
x=gi();y=gi();z=gi();
adde(x,y,z);adde(y,x,z);
}
m=gi();
for(i=1;i<=m;i++){
l=gi();r=gi();x=gi();
if(l<=x&&x<=r)
ans[i]=0;
else{
Q[x].push_back((node){i,l,r});
ans[i]=0x3f3f3f3f;
}
}
TDC(1,n);
for(i=1;i<=m;i++)
printf("%d\n",ans[i]);
}
std:
#include<cstdio>
#include<cstring>
#include<cctype>
#include<iostream>
#include<algorithm>
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<n;++i)
scanf("%d%d%d",&a,&b,&c),make(a,b,c);
solve(1,0);
int q;
scanf("%d",&q);
int l,r,x,re;
while(q--){
scanf("%d%d%d",&l,&r,&x);
re=INF;
for(i=0;i<17;++i){
if(bel[i][x])
re=min(re,dis[i][x]+Query(Root[i][bel[i][x]],1,n,l,r));
}
printf("%d\n",re);
}
fclose(stdin);
fclose(stdout);
return 0;
}