記憶體限制:128 mib
時間限制:1000 ms
【題目描述】
某校開展了同學們喜聞樂見的陽光長跑活動。為了能「為祖國健康工作五十 年」,同學們紛紛離開寢室,離開教室,離開實驗室,到操場參加 3000 公尺長跑運 動。一時間操場上熙熙攘攘,摩肩接踵,盛況空前。 為了讓同學們更好地監督自己,學校推行了刷卡機制。 學校中有 n 個地點,用 1 到 n 的整數表示,每個地點設有若干個刷卡機。 有以下三類事件: 1、修建了一條連線 a 地點和 b 地點的跑道。 2、a 點的刷卡機台數變為了 b。 3、進行了一次長跑。問乙個同學從 a 出發,最後到達 b 最多可以刷卡多少 次。具體的要求如下: 當同學到達乙個地點時,他可以在這裡的每一台刷卡機上都刷卡。但每台刷 卡機只能刷卡一次,即使多次到達同一地點也不能多次刷卡。 為了安全起見,每條跑道都需要設定乙個方向,這條跑道只能按照這個方向 單向通行。最多的刷卡次數即為在任意設定跑道方向,按照任意路徑從 a 地點 到 b 地點能刷卡的最多次數。
【輸入描述】
輸入的第一行包含兩個正整數 n,m,表示地點的個數和操作的個數。 第二行包含 n 個非負整數,其中第 i 個數為第個地點最開始刷卡機的台數。 接下來有 m 行,每行包含三個非負整數 p,a,b,p 為事件型別,a,b 為事件 的兩個引數。 最初所有地點之間都沒有跑道。 每行相鄰的兩個數之間均用乙個空格隔開。表示地點編號的數均在 1 到 n 之間,每個地點的刷卡機台數始終不超過 10000,p=1,2,3。
【輸出描述】
輸出的行數等於第 3 類事件的個數,每行表示乙個第 3 類事件。如果該情況 下存在一種設定跑道方向的方案和路徑的方案,可以到達,則輸出最多可以刷卡 的次數。如果 a 不能到達 b,則輸出-1。
輸入樣例:
9 31
10 20 30 40 50 60 70 80 90
3 1 2
1 1 3
1 1 2
1 8 9
1 2 4
1 2 5
1 4 6
1 4 7
3 1 8
3 8 8
1 8 9
3 8 8
3 7 5
3 7 3
1 4 1
3 7 5
3 7 3
1 5 7
3 6 5
3 3 6
1 2 4
1 5 5
3 3 6
2 8 180
3 8 8
2 9 190
3 9 9
2 5 150
3 3 6
2 1 210
3 3 6
輸出樣例:
-1
-180
170180
170190
170250
280280
270370
380580
感覺好lct啊。。。
先考慮乙個簡單的問題:
如何在乙個支援加邊的圖中維護兩點的連通性?
這不無腦並查集嗎。。。
再考慮乙個『簡單』的問題:
如何在乙個支援加邊的圖中維護兩點是否在同乙個邊雙連通分量?
似乎不會。。。
發現形成的第乙個邊雙連通分量一定是乙個環
想了一下,發現可以用lct+兩個並查集
先用乙個並查集check來維護連通性
再用乙個並查集real來維護邊雙連通分量的集合
如果u,v不連通,就把它們在check上合併
如果u,v連通但不在乙個邊雙連通分量,就把它們在lct上的路徑spilt出來,把路徑上的點乙個乙個在real上合併
感覺會t,於是我們縮一下點,把已經合併了real的點從lct中刪掉,只保留它們的祖宗,祖宗要統計它們的所有資訊
如果u,v在同乙個邊雙連通分量裡,就不管了
讓我們回到這個題,我們任務的就是求兩點路徑的點權和+兩點路徑上的邊雙連通分量總點權和
我們就可以用上面的思路來維護邊雙連通分量的點權和
於是我們維護的就是乙個由邊雙連通分量祖先構成的lct
如圖:
如果在已刪除節點之間連邊,就會使兩個邊雙祖先合併,就會刪掉其中之一
所以不同祖先的已刪除節點都無連邊。
**實現還有許多細節:
#include#include#includeusing namespace std;
#define n 100005
int n,m,val[n],a[n];//a是實際點權,val是祖先點權
struct node
int find(int x)
void uni(int x,int y)
}real,check;
int fa[n],ch[n][2],sum[n];
bool rev[n];
inline bool pdc(int x)
inline bool pdr(int x)
inline void pushdown(int x)
}void update(int x)
inline void rot(int x)
void pdpath(int x)
inline void splay(int x)
inline void access(int x)
}inline void beroot(int x)
inline void link(int x,int y)
void dfs(int &u,int d)//dfs只找lct上的節點(即未刪除節點)
int main()
else
} else if(op==2)
else
u=real.find(u);v=real.find(v);
beroot(u);access(v);splay(v);
printf("%d\n",sum[ch[v][0]]+val[v]);
} }}
好久都沒寫lct了。。。 jzoj 2016 5 14noip模擬賽C 總結
久違的noip模擬賽 先看第一題,dp想了一下複雜度太高,貪心的話八成會有反例 算了不糾結第一題了,先瞄一眼其他題 然後看第二題,咦矩形是什麼?懵了三秒,論智商的重要性 矩形怎麼判來著?又懵三秒 哦哦原來是送分題啊,那看第三題 嗯.覺得是先求每一行拿k個的最大價值,然後再去揹包這nm個貨物,使得其總...
2017 04 02 NOIP 普及組 模擬賽C組
總結 本次比賽310分 on3 呵呵呵呵 首先,一開始,開啟題目,發現b組可以迅速ac1題,但還是怕怕,慫回c組。8點30分,毫無頭緒地刷第2題。突然發現可以尋找中位數的方法去尋找士兵集合的那一列。9點30分,找出規律 士兵在同一列時如何站一列 10點,刷出t1和t2。t1是之前有過印象,於是純模擬...
2019 06 09 NOIP普及組 模擬賽C組
超連結為pdf題面,請先登入。渣題用s來表示長城的長度,t來表示目前的所用的時間。不斷地讀入a,b,t,而t不斷地加 b a 1 t,表示這一段所用的時間。最後s不斷減掉 bi ai 1,則就是剩下的長度了。最後t還要加上加上s1,計算普通的長城的時間。bas code include int s,...