東東的高速之旅 (線段樹維護區間最小值)(模擬賽)

2021-07-24 07:59:33 字數 4301 閱讀 3904

東東的高速之旅(highway.pas/.c/.cpp)

題目描述

一天東東爸 帶東東回老家,開車行駛在寬闊的高速公路上。東東思維本來就發散,讓他無聊的坐幾個小時他一定會無聊的。所以東東爸 就給他準備一道有關高速公路的問題,讓他在無聊的旅途中平添些樂趣。

題目是這樣的:行駛在高速上的車輛會對高速造成一定的損傷。假設一條高速公路被收費站分成了若干段,整條高速公路有乙個耐久度w。如果一輛汽車從s到t,s到t之間的高速公路的耐久度就會減少d。一旦某段公路的耐久度小於或等於0,這段公路就會永久性地毀壞,任何汽車也就無法通過已經毀壞的地方。

有一種維護車從s到t,可以將途中高速公路的耐久度增加r,並且不會造成公路耐久度的降低。雖然有維護車的存在,但是已經毀壞的某段路仍然無法修復。

東東的任務就是統計一下一共有多少輛汽車可以成功通行。

東東拿到題目,異常興奮,爭取在下高速的時候得到答案。但是題目真的太難了,快下高速了,東東還是沒有得到結果,急的滿頭大汗,就給你打了**,你能幫東東得到正確的結果麼?

輸入格式

第一行是三個正整數n、m和w。表示高速公路被分成了n段,有m輛車依次通過,整段高速公路的初始的耐久度為w。

以下m行每行描述一輛車,格式如下:

1 s t d:一輛汽車準備通過區間[s,t]。如果區間[s,t]裡面有任何乙個地方損毀了,這輛汽車就會取消整個通行計畫;否則這輛汽車就可以成功通過區間[s,t],並且使這個區間的耐久度減少d。即使通過之後會把某些地方毀壞了也是能夠通過的。

2 s t r:一輛維修車通過區間[s,t],為這段公路的耐久度增加r。如果區間[s,t]裡面有任何乙個地方損毀了,這輛維修車也會取消整個通行計畫。

其中對於所有的區間[s,t]:表示從第s段的開始,到達第t段的結尾。

輸出格式

輸出乙個數,表示有多少汽車可以成功通行。

樣例輸入

3 4 2

2 1 3 3

1 1 2 3

1 2 3 2

1 1 3 1

樣例輸出

3 資料範圍與約定

對於30%的資料 n,m <= 100

對於50%的資料 n,m <= 1000

對於100%的資料 n,m<= 100000

1≤w≤1000,1≤s≤t≤n,1≤d≤1000,1≤r≤1000

本題用lazy標記的線段樹去維護資料,即可。需要注意的是維護車輛也是汽車,也要統計到答案中。

program mys;

type

ab=record

l,r,w,c:longint;

end;

var n,m,e,z,s,t,p,i,tot,ans,sum:longint;

f:array[0..1000000]of ab;

procedure

built

(x,y,i:longint);

var mid:longint;

begin

f[i].l:=x;

f[i].r:=y;

if x=y then

begin

f[i].w:=e;

exit;

end;

mid:=(x+y)div

2;built(x,mid,i*2);

built(mid+1,y,i*2+1);

if f[i*2].w<=f[i*2+1].w then

f[i].w:=f[i*2].w

else

f[i].w:=f[i*2+1].w;

end;

function

pd(x,y,k:longint):boolean;

var mid:longint;

begin

if (f[k].l=x)and(f[k].r=y) then

begin

if f[k].c<>0

then

begin

f[k*2].w:=f[k*2].w-f[k].c;

f[k*2].c:=f[k*2].c+f[k].c;

f[k*2+1].w:=f[k*2+1].w-f[k].c;

f[k*2+1].c:=f[k*2+1].c+f[k].c;

f[k].c:=0;

end;

if f[k].w<=0

then

exit(false)

else

exit(true);

end;

if f[k].c<>0

then

begin

f[k*2].w:=f[k*2].w-f[k].c;

f[k*2].c:=f[k*2].c+f[k].c;

f[k*2+1].w:=f[k*2+1].w-f[k].c;

f[k*2+1].c:=f[k*2+1].c+f[k].c;

f[k].c:=0;

end;

mid:=(f[k].l+f[k].r)div

2;if y<=mid then

exit(pd(x,y,k*2))

else

if x>mid then

exit(pd(x,y,k*2+1))

else

begin

if pd(x,mid,k*2) and pd(mid+1,y,k*2+1) then

exit(true)

else

exit(false);

end;

if f[k*2].w<=f[k*2+1].w then

f[k].w:=f[k*2].w

else

f[k].w:=f[k*2+1].w;

end;

procedure

change

(x,y,k:longint);

var mid:longint;

begin

if (f[k].l=x)and(f[k].r=y) then

begin

if f[k].c<>0

then

begin

f[k*2].w:=f[k*2].w-f[k].c;

f[k*2].c:=f[k*2].c+f[k].c;

f[k*2+1].w:=f[k*2+1].w-f[k].c;

f[k*2+1].c:=f[k*2+1].c+f[k].c;

f[k].c:=0;

end;

f[k].w:=f[k].w-p;

f[k].c:=f[k].c+p;

exit;

end;

if f[k].c<>0

then

begin

f[k*2].w:=f[k*2].w-f[k].c;

f[k*2].c:=f[k*2].c+f[k].c;

f[k*2+1].w:=f[k*2+1].w-f[k].c;

f[k*2+1].c:=f[k*2+1].c+f[k].c;

f[k].c:=0;

end;

mid:=(f[k].l+f[k].r)div

2;if y<=mid then change(x,y,k*2)

else

if x>mid then change(x,y,k*2+1)

else

begin

change(x,mid,k*2);

change(mid+1,y,k*2+1);

end;

if f[k*2].w<=f[k*2+1].w then

f[k].w:=f[k*2].w

else

f[k].w:=f[k*2+1].w;

end;

begin

assign(input,'highway.in');reset(input);

assign(output,'highway.out');rewrite(output);

readln(n,m,e);

built(1,n,1);

ans:=0;

for i:=1

to m do

begin

readln(z,s,t,p);

if z=2

then p:=-p;

if pd(s,t,1) then

begin

inc(ans);

change(s,t,1);

end;

end;

writeln(ans);

close(input);

close(output);

end.

滑動視窗(poj,線段樹維護區間最值)

現在有一堆數字共n個數字 n 10 6 以及乙個大小為k的視窗。現在這個從左邊開始向右滑動,每次滑動乙個單位,求出每次滑動後視窗中的最大值和最小值。例如 the array is 1 3 1 3 5 3 6 7 and k 3.輸入格式 輸入一共有兩行,第一行為n,k。第二行為n個數 輸出格式 輸出...

線段樹維護區間01

g.小 w 開關燈 problem 4467 discussion description 晚上到家小 w 通過開關燈來保持自己神經的興奮以便清醒地理筆記。n n 2 n 100,000 2 n 100,000 盞燈被連續的編號為 1 n 1 n 剛回到家的時候,所有的燈都是關閉的。小w 通過 n ...

最敏捷的機械人(線段樹維護區間最值)

題面 wind設計了很多機械人。但是它們都認為自己是最強的,於是,一場比賽開始了 機器人們都想知道誰是最敏捷的,於是它們進行了如下乙個比賽。首先,他們面前會有一排共n個數,它們比賽看誰能最先把每連續k個數中最大和最小值寫下來,當然,這些機械人運算速度都很,它們比賽的是誰寫得快。但是wind也想知道答...