東東的高速之旅(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也想知道答...