題目描述
西瓜們生活在編號 1···n 的 n個平行時空中,2n−2 臺時光機將這些平行時空聯絡在一起。
一台時光機有 3個整數引數 u,v,t 表示從時空 u 可以花費 t 的時間穿梭到時空 v。
為了確保時空之間可以相互穿梭,同時方便作為現世的 1號時空的通行,西瓜們將這些時光機進行分工:前 n−1 臺
時光機確保從 1號時空可以直接 / 間接抵達任意時空,後 n−1臺時光機負責從 2···n號時空直接返回 1號時空。
q1個西瓜希望從一些時空穿梭到一些時空。顯然,智慧型的西瓜們會選擇最省時的路線。然而,時光機並不穩定,
在此期間,時光機的執行時間會發生q2次變化。西瓜王被吃了,希望你告訴他的子民西瓜們當前最優路線所需的
時間。正解
dfs序+線段樹
其中dfs序是為了把區間不連貫的樹整理成一段連續的區間,為線段樹的使用提供方便。線段樹用來維護區間最小值。
對於dfs序,我們給每個點第一次進入dfs時特別標記一次,給其專門乙個編號;離開dfs時公用當時的編號即可,因為這個編號足以包含它的所有子樹的節點。
我們定義線段樹為求從ql到qr內一節點出發,直接到達1後再回到該節點的最短路徑。線段樹常規求區間最小值。因為涉及到路徑修改,對於一條從1出發的路徑(起始點x,終止點y)修改,這一改變會影響到y子樹內的所有節點,要進行(l[y],r[y])區間的修改。對於回到1的路徑(起始點x),只對x回到1有影響(因為定義裡寫的是直接),故只需修改(l[x],l[x])區間。
詢問的話要分兩種情況來考慮。
一是y是x子樹內的一節點,那麼直接由x到y為最短路徑。此時會有 l[x]y->1)-dis(y->1)-( dis(1->x->1)+dis(x->1) )。
二是x需要先到x子樹內一節點,然後向上到1,再到y。這樣的答案為dis(1->x'->1)-( dis(1->x->1)-dis(x->1) )+( dis(1->y->1)-dis(y->1) ),其中dis(1->x'->1)-( dis(1->x->1)-dis(x->1) )能求出x回到1的最短距離。
總結
本題關鍵:一是乙個判斷和求乙個距離,判斷是否在其一在另一子樹內,然後求出兩點間直接到達的距離;二是求乙個最短和乙個距離,從x回1的最短路徑,從1到y的距離。
然後利用線段樹可以快速求到區間最小值,巧妙地設計了記錄每個節點一來一回的距離的線段樹,包含了完整的情況。這樣再利用加加減減就可以表達出各段路徑的距離了。
**
#include#include#includeusing namespace std;
typedef long long ll;
const int maxn=2e5+10;
inline int read()
int n,q;
int l[maxn],r[maxn];
//***********鄰接表**************
struct edge
e[maxn*2];int last[maxn],len=0;
int to[maxn];
void ins(int x,int y,int c)
void ins2(int x,int y,int c)
int id=0,yss[maxn];
ll g[maxn];
void dfs(int x)
r[x]=id;
}//***********線段樹****************
ll mn[maxn*2],lazy[maxn*2];//線段樹輔助詢問從1到x再由x到1的最小路徑
void bt(int x,int l,int r)
int mid=l+r>>1;
int lc=x<<1,rc=lc|1;
bt(lc,l,mid);
bt(rc,mid+1,r);
mn[x]=min(mn[lc],mn[rc]);lazy[x]=0;
}void pushdown(int x)
void add(int x,int l,int r,int ql,int qr,int k)
if(lazy[x]!=0) pushdown(x);
int mid=l+r>>1;
int lc=x<<1,rc=lc|1;
if(qr<=mid) add(lc,l,mid,ql,qr,k);
else if(mid+1<=ql) add(rc,mid+1,r,ql,qr,k);
else add(lc,l,mid,ql,mid,k),add(rc,mid+1,r,mid+1,qr,k);
mn[x]=min(mn[lc],mn[rc]);
}ll ask(int x,int l,int r,int ql,int qr)
if(lazy[x]!=0) pushdown(x);
int mid=l+r>>1;
int lc=x<<1,rc=lc|1;
if(qr<=mid) return ask(lc,l,mid,ql,qr);
else if(mid+1<=ql) return ask(rc,mid+1,r,ql,qr);
else return min(ask(lc,l,mid,ql,mid),ask(rc,mid+1,r,mid+1,qr));
}//*********************************
int main()
else//x->(x子樹內一子節點->)1->y
}else
{ if(x
CTSC2016時空旅行
當時看這道題ac的人數比較多,就開了這道題。很容易發現是這是乙個有關凸包的題。然後不知道怎麼維護凸包,一直在想cdq,感覺複雜度不行,於是被這玩意難住了 幸好有親學長yyh造福人類的題解 十分詳細,而且相對容易看懂些,腦迴路跟我差不多。發現主要是我沒學線段樹標記永久化,所以去學了一下這個東西 大概就...
CTSC2016 時空旅行
鏈結 題解首先要發現答案要我們求這個式子 ans min bigl x i x 2 c i bigr 顯而易見的是這種時空嫁接的關係會形成一棵樹。但是我們並不能像 noi2014 購票那樣直接在樹上維護一條鏈的棧,因為每個點代表的既有可能是加入乙個點,又有可能是刪除乙個點。考慮每個點的存在時間都是一...
時空旅行的可能性(無聊研究社)
經濟不好的時候,人一般都沒有什麼愛好,所以這段時間只能以看相對論啊,宇宙起源之類的東西拿來消遣,說實話這類消遣是最廉價的,成本不會高於宅男們欣賞蒼老師們的表演的成本。仔細的閱讀了一些這些大師們的著作後,我發現,時空旅行理論上可以,但實際上很難,因為 1 如果靠速度去旅行,宇宙天體之間的距離動不動就是...