瓜瓜的時空旅行

2021-08-19 08:11:41 字數 2772 閱讀 8144

題目描述

西瓜們生活在編號 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 如果靠速度去旅行,宇宙天體之間的距離動不動就是...