洛谷 P5445 路燈

2022-03-12 12:19:42 字數 2486 閱讀 3244

題意見洛谷。

首先考慮實時維護\(\forall i,j\in[1,n]\),目前有多少時刻滿足能從\(i\)到達\(j\)。

顯然,\(i\)能到達\(j\)當且僅當\(i,j\)在同乙個亮燈連續段裡。將當前狀態剖成若干個極大亮燈連續段,那麼能否到達關於\(i,j\)兩維的函式應該是由這些連續段,每段分別在\(i\)軸和\(j\)軸上作為兩條鄰邊、\(j=i\)上的一段作為副對角線的一些充滿\(1\)的正方形組成的,其他地方都是\(0\)。(別問為啥不貼圖,問就是我不是良心博主)

那麼在某一時刻的答案函式就是之前所有時刻的所對應的上述01函式之和。考慮實時維護這個答案函式(二維函式,即乙個矩陣)。

一種很容易想到的方法是遞推,每次將當前時刻的01函式加到當前維護的答案函式裡面去。當前時刻的01函式顯然是由上一時刻的01函式進行常數次矩形修改得來的(開燈就是連線兩邊接壤的\(1\)矩形並補全,關燈就是從所在\(1\)矩形斷開,至於如何維護這些連續段,set即可,太簡單不多說),而將01函式加到答案函式裡去又等價於對答案矩陣進行若干次(這裡不是常數次了,而是連續段個數次,即\(1\)矩形個數次)矩形增加\(1\)。這裡對01函式的更新顯然是力所能及的,而對答案函式的更新的複雜度就沒法保證了。

不難發現,這裡對01函式的更新是若干次矩形加\(1\),其中\(1\)是個常數,而這些矩形隨時刻遞增又是常數差異的,就一臉可以優化成在這些常數級別的差異上增加非常數,從而保證複雜度。

考慮乙個01函式關於時刻的三維函式。考慮當前答案函式的每一處在這個三維函式上的意義:顯然是從當前時刻斷開時間軸得到的縱切面的左邊的所有此處的和。這是一些\(0/1\)的和,\(0\)顯然不用考慮,剩下來就是一些\(1\)的區間,設為\([l_1,r_1],[l_2,r_2],\cdots,[l_k,r_k]\),那麼這個和就是\(\sum\limits_^k(r_i-l_i+1)\)。考慮在乙個區間開始的時候給此處貢獻上\(-l_i\),在區間結束的時候給此處貢獻上\(r_i+1\)。此時增加量顯然不是常數了,我們來看看增加次數有沒有減少。區間開始和區間結束的時候,就是相鄰01函式差異對此處影響的時候,每次時刻的遞推都只有01函式差異的矩形量次矩形增加,哦吼,可以了。需要注意的是,若當前要查詢的那處在01函式中為\(1\)的話,那麼第\(k\)個區間還未結束,我們要強行令它結束,即在答案函式在此處的值的基礎上再加上當前時刻。

(上面這一段重要的轉化是本題的瓶頸。個人感覺這個哲學思想理解的還不是很透徹,大概以後重點做ds的時候題做多了感覺就上來了吧。)

接下來就是個矩形增加、單點查詢的事了。看起來能夠線段樹套動態開點線段樹,但寫到一半才發現外層線段樹的懶標記無法\(\mathrm o(1)\)儲存。於是想到將修改和查詢範圍顛倒的方式:差分。考慮二維差分,這樣一次矩形增加轉化為\(4\)次單點增加,單點查詢轉化為字首矩形求和。這就是個經典的二維數點模型,寫一發bit套動態開點線段樹即可(萌新第一次寫這個,多多關照)。二維數點應該是有其他方法的(如cdq分治),然而我還沒有系統的學這一塊,不管,而且這題重點不在這裡。

btw,這是我第二次寫vector動態開點資料結構(第一次是列隊),犯了跟列隊同樣的錯誤(ub+vector分配記憶體原理造成賦不進去值)。多錯幾次就不會犯了。

**:

#includeusing namespace std;

#define pb push_back

#define mp make_pair

#define x first

#define y second

const int inf=0x3f3f3f3f;

int lowbit(int x)

const int n=300000;

int n,qu;

char a[n+5];

struct segtree;

#define lson(p) nd[p].lson

#define rson(p) nd[p].rson

#define l(p) nd[p].l

#define r(p) nd[p].r

#define sum(p) nd[p].sum

vectornd;

int nwnd(int l=1,int r=n))),nd.size()-1;}

void init()));

nwnd();

} void add(int x,int v,int p=1)

else

} int _sum(int l,int r,int p=1)

};struct bitree

void add(int x,int y,int v)

void add(int l1,int r1,int l2,int r2,int v)

int val(int x,int y)

}bit;

int main()

else

} else

} return 0;

}

P5445 APIO2019 路燈(樹套樹)

p5445 apio2019 路燈 轉化為平面上的座標 x,y x,y se t set維護連續區間.用樹套樹維護矩陣加法,單點查詢。注意維護矩陣差分的時候,x,y,v 是對 x,y n 1,n 1 的矩陣做出貢獻 include include include include define ri ...

洛谷 P1220 關路燈

某一村莊在一條路線上安裝了n盞路燈,每盞燈的功率有大有小 即同一段時間內消耗的電量有多有少 老張就住在這條路中間某一路燈旁,他有一項工作就是每天早上天亮時一盞一盞地關掉這些路燈。為了給村里節省電費,老張記錄下了每盞路燈的位置和功率,他每次關燈時也都是盡快地去關,但是老張不知道怎樣去關燈才能夠最節省電...

洛谷 P1220 關路燈

某一村莊在一條路線上安裝了n盞路燈,每盞燈的功率有大有小 即同一段時間內消耗的電量有多有少 老張就住在這條路中間某一路燈旁,他有一項工作就是每天早上天亮時一盞一盞地關掉這些路燈。為了給村里節省電費,老張記錄下了每盞路燈的位置和功率,他每次關燈時也都是盡快地去關,但是老張不知道怎樣去關燈才能夠最節省電...