BZOJ2325 ZJOI2011 道館之戰

2022-03-29 16:21:41 字數 4243 閱讀 9290

bzoj2325: [zjoi2011]道館之戰

某$zoj$上竟然是個許可權題。。。

沒錢氪金的窮$afo$狗老淚縱橫。。。

附上大美洛谷的題面:

p4679 [zjoi2011]道館之戰

口袋妖怪(又名神奇寶貝或寵物小精靈)紅/藍/綠寶石中的水系道館需要經過三個冰地才能到達館主的面前,冰地中的每乙個冰塊都只能經過一次。

當乙個冰地上的所有冰塊都被經過之後,到下乙個冰地的樓梯才會被開啟。

三個冰地分別如下:

當走出第三個冰地之後,就可以與館主進行道館戰了。

館主發現這個難度太小,導致經常有挑戰者能通過,為了加大難度,將道館分成了n個房間,任意兩個房間之間均有且僅有一條路徑相連,即這n個房間構成乙個樹狀結構。

每個房間分成了a和b兩個區域,每一區域都是乙個薄冰塊或者障礙物。

每次只能移動到相鄰房間的同一類區域(即若你現在在這個房間的a區域,那麼你只能移動到相鄰房間的aa區域)或這個房間的另一區域。

現在挑戰者從房間u出發,館主在房間v,那麼挑戰者只能朝接近館主所在房間的方向過去。

一開始挑戰者可以在房間u的任意乙個冰塊區域內。

如果挑戰者踩過的冰塊數達到了最大值(即沒有一種方案踩過的冰塊數更多了),那麼當挑戰者走到最後乙個冰塊上時,他會被瞬間傳送到館主面前與館主進行道館戰。

自從館主修改規則後已經經過了m天,每天要麼是有乙個挑戰者來進行挑戰,要麼就是館主將某個房間進行了修改。

對於每個來的挑戰者,你需要計算出他若要和館主進行戰鬥需要經過的冰塊數。

輸入格式:

第一行包含兩個正整數n和m。

第2行到第n行,每行包含兩個正整數x和y,表示一條連線房間x和房間y的邊。房間編號為1⋯n。

接下來n行,每行包含兩個字元。第n+k行表示房間k的兩個區域,第乙個字元為a區域,第二個字元為b區域。

其中「.」(ascii碼為46)表示是薄冰塊,「#」(ascii碼為35)表示是障礙物。

最後的m行,每行乙個操作:

cus:將房間u裡的兩個區域修改為s。

quv:詢問挑戰者在房間u,館主在房間v時,挑戰者能與館主進行挑戰需要踩的冰塊數。

如果房間u的兩個區域都是障礙物,那麼輸出0。

輸出格式:

包含若干行,每行乙個整數。即對於輸入中的每個詢問,依次輸出乙個答案。

輸入樣例: 

5 3

1 22 3

2 41 5

.#..

#..#

..q 5 3

c 1 ##

q 4 5

輸出樣例: 

6

3

測試點1~6:n≤1000,m≤10000

測試點7~15:n≤30000,m≤80000

測試點16~20:n≤50000,m≤100000

這個題的題目描述爛到家了。。。

本蒟蒻看了至少半個小時,翻了至少$6$篇題解,才看懂題面。。。

題意補充戳這。

首先樹上問題一發樹剖轉成鏈上問題沒得說。

在當前區間中,我們發現其實就是乙個$n\times 2$的矩陣。

感覺就是把堵塞的交通的圖順時針轉了$90$。。。

設:$data[0][0]$表示從左上走到右上的最長路,$data[0][1]$表示從左上到右下,$data[1][0],data[1][1]$以此類推。

$maxd[0][0]$表示從左上出發能走的最大距離,$maxd[0][1]$表示左下的,$maxd[1][0]$表示右上,$maxd[1][1]$表示右下。

然後就是喪心病狂的$pushup$(為了方便我寫成了結構體):

friend segment_tree operator +(const segment_tree &p,const segment_tree &q)
簡直了。。。我也沒有什麼辦法。。。出題人大$duliu$。。。

接下來就是樹剖的合併了。

我們注意到這其實是兩條鏈:$u->lca(u,v),lca(u,v)->v$

並且這兩條鏈得分開維護。

為什麼?

因為這玩意的有序性。。。

而且就算知道了這個也不行,還要把$u->lca(u,v)$反向。

同樣是因為這玩意的有序性。。。

然後我就因為邊界問題調了半小時。。。

$afo$後碼力極度下降。。。

附上奇醜無比的**:(198行。。。強迫症患者很難受。。。)

#include#include#include#include#define lson rt<<1

#define rson rt<<1|1

#define lside(x) b[x].l

#define rside(x) b[x].r

#define maxn 50010

#define max (1<<30)

using namespace std;

int n,m,c=1,d=1;

int val[maxn][2],head[maxn],deep[maxn],son[maxn],size[maxn],fa[maxn],id[maxn],pos[maxn],top[maxn];

struct edgea[maxn<<1];

struct segment_tree

void reverse()

friend bool empty(const segment_tree &x)

void value(const int &p,const int &q)

else if(p==1)

else if(q==1)

else

} friend segment_tree operator +(const segment_tree &p,const segment_tree &q)

}b[maxn<<2];

inline int read()

while(c>='0'&&c<='9')

return date*w;

}inline void add(int x,int y)

void dfs1(int rt) }}

void dfs2(int rt,int f)

}inline void pushup(int rt)

void buildtree(int l,int r,int rt)

int mid=l+r>>1;

buildtree(l,mid,lson);

buildtree(mid+1,r,rson);

pushup(rt);

}void update(int k,int p,int q,int rt)

int mid=lside(rt)+rside(rt)>>1;

if(k<=mid)update(k,p,q,lson);

else update(k,p,q,rson);

pushup(rt);

}segment_tree query(int l,int r,int rt)

int query_path(int x,int y)

else

} if(deep[x]<=deep[y])right=query(id[x],id[y],1)+right;

else left=query(id[y],id[x],1)+left;

left.reverse();

ans=left+right;

return max(ans.maxd[0][0],ans.maxd[0][1]);

}void work()

else }}

void init()

deep[1]=1;

dfs1(1);

dfs2(1,1);

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

buildtree(1,n,1);

}int main()

BZOJ1003 ZJOI 物流運輸

物流公司要把一批貨物從碼頭a運到碼頭b。由於貨物量比較大,需要n天才能運完。貨物運輸過程中一般要轉停好幾個碼頭。物流公司通常會設計一條固定的運輸路線,以便對整個運輸過程實施嚴格的管理和跟蹤。由於各種因素的存在,有的時候某個碼頭會無法裝卸貨物。這時候就必須修改運輸路線,讓貨物能夠按時到達目的地。但是修...

ZJOI2007 BZOJ1059 矩陣遊戲

description 第一行包含乙個整數t,表示資料的組數。接下來包含t組資料,每組資料第一行為乙個整數n,表示方陣的大小 接下來n行為乙個n n的01矩陣 0表示白色,1表示黑色 output 輸出檔案應包含t行。對於每一組資料,如果該關卡有解,輸出一行yes 否則輸出一行no。sample i...

bzoj 1096 ZJOI2007 倉庫建設

time limit 10 sec memory limit 162 mb submit 3607 solved 1582 submit status discuss l公司有n個工廠,由高到底分布在一座山上。如圖所示,工廠1在山頂,工廠n在山腳。由於這座山處於高原內 陸地區 乾燥少雨 l公司一般把...