Tyvj4878 道路修建(環套樹 單調佇列)

2021-08-08 21:52:31 字數 1466 閱讀 8397

題面

題意:給你3000棵環套樹,邊長都為1,問兩個點的最短距離的最大值。

根據環套樹的套路,先把環找出來,然後dfs每棵外向樹。對於每個點,記錄l1為該點向下最長鏈的深度,l2為為該點向下次長鏈的深度,l1+l2就可能成為答案。這樣就處理了路徑在每棵樹上的情況。

我們考慮路徑跨越了環的情況。想到在吃雞時跑毒的短邊原則,最短路肯定在環的小半圈。

設環的長度為len,對於環上的第i個點和第j個點,j>i,最長路徑為

l1[i]+l1[j]+min(j-i,len-j+i)。

我們把min拆出來,就等價於把環複製一遍,對於點i,和它的前len/2個點計算距離,距離為l1[i]+l1[j]+i-j。就是求乙個滑動區間的l1[j]-j的最大值,就是乙個單調佇列了。

#include 

#include

#include

#include

#include

#include

#include

#include

using namespace std;

#define mmst(a, b) memset(a, b, sizeof(a))

#define mmcp(a, b) memcpy(a, b, sizeof(b))

typedef long long ll;

const int n=3030;

int n,m,u[n],v[n];

int to[n*2],nex[n*2],head[n],cnt;

int fa[n],l1[n],l2[n],c[2

*n],num;

int ans;

bool cir[n],vis[n];

intq[2*n];

void add(int u,int v)

void dfs2(int

x) else

if(l1[to[h]]+1>l2[x])

l2[x]=l1[to[h]]+1;

}ans=max(ans,l1[x]+l2[x]);

}void dfs(int

x) c[++num]=to[h];

cir[to[h]]=1;

for(int i=1;i<=num;i++)

dfs2(c[i]);

return;

}fa[to[h]]=x;

dfs(to[h]);

}}int get(int

x)int main()

for(int i=num+1;i<=num*2;i++)

printf("%d\n",ans);

}return

0;}

昨晚看完了《我女友與…的慘烈…》,可能是我太喜歡夏川真涼了,整晚都感覺好虐,然後我今天就壞掉了。

kisekiより,約束が好き

2017 5 11 道路修建 思考記錄

這個線段樹一眼秒了 主要是有前面的思考經驗 就是維護兩個列對應線段上的形態。比較好想的 但資料結構題有個特點 使你知道結構也不會做 會做也會很大概率爆零.所以資料結構題必須 小資料 特殊資料 對拍!不然怎麼掛的都不知道 敲 錯 調 查 調 搞了乙個上午 這個題用線段樹維護 乙個最小值 合併時需要考慮...

bzoj2435 道路修建

道路修建 題目背景 bzoj2435 分析 暴力 dfs 突如其來的傻題 get 直接 dfs,每乙個點對答案的貢獻是,abs n size cur size cur w w 為這個點與父親的連邊的權值 然後就沒有然後了 source created by scarlyw include inclu...

cumtoj修建道路 LCA倍增

題目描述 n nn個點n 1 n 1n 1條邊,點之間兩兩連通,每次詢問3 33個點,求使這3 33個點連通的最小花費。1 n q 1 05 1 leq n,q leq 10 5 1 n,q 105 因為給的是一顆樹,最終的答案就是dis t x,y d ist y,z dis t x,z 2.fr...