bzoj5192 [Usaco2018 Feb]New Barns
http://www.elijahqi.win/2018/03/06/bzoj5192-usaco2018-febnew-barns/
Description
FarmerJohn注意到他的奶牛們如果被關得太緊就容易吵架,所以他想開放一些新的牛棚來分散她們。每當FJ建造一
個新牛棚的時候,他會將這個牛棚用至多一條雙向道路與一個現有的牛棚連線起來。為了確保他的奶牛們足夠分散
,他有時想要確定從某個特定的牛棚出發,到它能夠到達的最遠的牛棚的距離(兩個牛棚之間的距離等於從一個牛
棚出發到另一個之間必須經過的道路條數)。FJ總共會給出Q(1≤Q≤10^5)次請求,每個請求都是“建造”和“
距離”之一。對於一個建造請求,FJ建造一個牛棚,並將其與至多一個現有的牛棚連線起來。對於一個距離請求,
FJ向你詢問從某個特定的牛棚通過一些道路到離它最遠的牛棚的距離。保證詢問的牛棚已經被建造。請幫助FJ響應
所有的請求。
Input
第一行包含一個整數Q
以下Q行,每行包含一個請求。每個請求的格式都是“B p”或是“Q k”
分別告訴你建造一個牛棚並與牛棚p連線,或是根據定義求從牛棚k出發最遠的距離。
如果p=-1,則新的牛棚不會與其他牛棚連線。
否則,p是一個已經建造的牛棚的編號。
牛棚編號從1開始,所以第一個被建造的穀倉是1號穀倉,第二個是2號穀倉,以此類推。
Output
對於每個距離請求輸出一行。注意一個沒有連線到其他牛棚的牛棚的最遠距離為0
Sample Input
7
B -1
Q 1
B 1
B 2
Q 3
B 2
Q 2
Sample Output
0
2
1
輸入樣例對應下面的牛棚網:
(1)
\
(2)---(4)
/
(3)
對於請求1,我們建造牛棚1。對於請求2,我們詢問從1出發到最遠連線的牛棚的距離。由於牛棚1沒有與其他牛棚
連線,所以回答是0。對於請求3,我們建造牛棚2並將其與牛棚1連線。對於請求4,我們建造牛棚3並將其與牛棚2
連線。對於請求5,我們詢問從3出發到最遠連線的牛棚的距離。在這時,最遠的是牛棚1,距離為2單位。對於請求
6,我們建造牛棚4並將其與牛棚2連線。對於請求7,我們詢問從2出發到最遠連線的牛棚的距離。所有其他三個牛
棚1,3,4都與2相距相同的距離1,所以這就是我們的回答。
題意:每次新增一個點 求距離這個點最遠的點是誰
注意有可能存在 這些點並不連通的情況
那麼題目沒有強制線上 首先我們離線進來把整個樹建好 那麼 對於這棵樹而言我相當於先點分一下 然後每次詢問的時候就是在我點分樹父節點裡找一個不是來自我的最大值加上我到x的距離即可 那該怎麼做 只需要維護幾個值即可 在這個點分樹上維護到我這個分治重心的最遠點是誰 還有最遠點屬於的子樹 還有不包含在最遠點子樹裡的次遠點 那麼每次新建一個節點相當於點分樹上這個節點我可以走了 那麼就直接做就好了 注意詢問的時候要判斷分治中心是否已經可以走 複雜度n*log(n)
#include<queue>
#include<cstdio>
#include<vector>
#include<cstring>
#include<algorithm>
#define inf 0x3f3f3f3f
#define N 110000
#define pa pair<int,int>
using namespace std;
inline char gc(){
static char now[1<<16],*S,*T;
if (T==S){T=(S=now)+fread(now,1,1<<16,stdin);if (T==S) return EOF;}
return *S++;
}
inline int read(){
int x=0,f=1;char ch=gc();
while(ch<'0'||ch>'9') {if (ch=='-') f=-1;ch=gc();}
while(ch<='9'&&ch>='0') x=x*10+ch-'0',ch=gc();
return x*f;
}
struct node{
int y,next;
}data[N<<1];
struct node1{
int x,op;
}qr[N];
struct node2{
int mx1,mxid,mx2;
}tree[N];
bool flag[N],visit[N];
int dep[N],num,h[N],n,m,sum,root,size[N];
vector<pa> par[N];
inline void insert1(int x,int y){
data[++num].y=y;data[num].next=h[x];h[x]=num;
data[++num].y=x;data[num].next=h[y];h[y]=num;
}
inline void dfs(int x,int fa){
size[x]=1;
for (int i=h[x];i;i=data[i].next){
int y=data[i].y;if (y==fa) continue;dfs(y,x);size[x]+=size[y];
}
}
inline void dfs1(int x,int f,int bl){
par[x].push_back(make_pair(dep[x],bl));
for (int i=h[x];i;i=data[i].next){
int y=data[i].y;if (visit[y]||y==f) continue;
dep[y]=dep[x]+1;dfs1(y,x,bl);
}
}
int f[N];
inline void get_root(int x,int fa){
f[x]=0;size[x]=1;
for (int i=h[x];i;i=data[i].next){
int y=data[i].y;if (y==fa||visit[y]) continue;
get_root(y,x);size[x]+=size[y];f[x]=max(f[x],size[y]);
}f[x]=max(f[x],sum-size[x]);
if (f[root]>f[x]) root=x;
}int fa[N];
inline void solve(int x){
visit[x]=1;int sum1=sum;dep[x]=0;
for (int i=h[x];i;i=data[i].next){
int y=data[i].y;if (visit[y]) continue;
dep[y]=1;dfs1(y,x,y);
}
for (int i=h[x];i;i=data[i].next){
int y=data[i].y;if (visit[y]) continue;
if(size[y]>size[x]) sum=sum1-size[x];else sum=size[y];
root=0;get_root(y,x);fa[root]=x;solve(root);
}
}
inline void change(int x){
int xx=fa[x];
for (int i=par[x].size()-1;~i;--i){
int d=par[x][i].first,bl=par[x][i].second;
//printf("%d %d\n",xx,d);
//printf("%d %d %d\n",tree[xx].mx1,tree[xx].mxid,tree[xx].mx2);
if (d>=tree[xx].mx1){
if (bl!=tree[xx].mxid) tree[xx].mx2=tree[xx].mx1;
tree[xx].mx1=d;tree[xx].mxid=bl;
}else if (bl!=tree[xx].mxid&&d>tree[xx].mx2) tree[xx].mx2=d;
xx=fa[xx];
}
}
inline int query(int x){
int tmp=tree[x].mx1,xx=fa[x];
for (int i=par[x].size()-1;~i;--i){
int d=par[x][i].first,bl=par[x][i].second;
//printf("%d\n",tmp);
if (flag[xx]){
// printf("%d %d\n",xx,d);
if(bl!=tree[xx].mxid) tmp=max(tmp,tree[xx].mx1+d);
else tmp=max(tmp,tree[xx].mx2+d);
}xx=fa[xx];
}return tmp;
}
int main(){
freopen("bzoj5192.in","r",stdin);
freopen("bzoj5192.out","w",stdout);
m=read();f[0]=inf;
for (int i=1;i<=m;++i){
char ch=gc();while(ch!='B'&&ch!='Q') ch=gc();int x=read();
if (ch=='B') {++n;if (x==-1) flag[n]=1;else insert1(n,x);qr[i].x=n;qr[i].op=1;}
else qr[i].op=2,qr[i].x=x;
}
for (int i=1;i<=n;++i){
if (!flag[i]) continue;dfs(i,i);sum=size[i];root=0;get_root(i,i);solve(root);
}memset(flag,0,sizeof(flag));
/*for (int i=1;i<=13;++i){
printf("%d %d\n",qr[i].x,qr[i].op);
}*/
for (int i=1;i<=m;++i){
if (qr[i].op==1) change(qr[i].x),flag[qr[i].x]=1;
else printf("%d\n",query(qr[i].x));
}
return 0;
}