深繪里一直很討厭雨天。
灼熱的天氣穿透了前半個夏天,後來一場大雨和隨之而來的洪水,澆滅了一切。
雖然深繪里家鄉的小村落對洪水有著頑固的抵抗力,但也倒了幾座老房子,幾棵老樹被連
根拔起,以及田地裡的糧食被弄得一片狼藉。
無奈的深繪里和村民們只好等待救濟糧來維生。
不過救濟糧的發放方式很特別。
首先村落裡的一共有n 座房屋,並形成乙個樹狀結構。然後救濟糧分m 次發放,每次選擇
兩個房屋(x,y),然後對於x 到y 的路徑上(含x 和y) 每座房子裡發放一袋z 型別的救濟糧。
然後深繪里想知道,當所有的救濟糧發放完畢後,每座房子裡存放的最多的是哪種救濟糧。
首先所有的操作是已經給定的,詢問都是固定的。
我們考慮在序列上做覆蓋,在左右端點加1減1,維護最大值即可。
如果在樹上,那我們先把樹剖成一條條鏈,再在上面做覆蓋即可。時間複雜度o(nl
og22
)可不可以不這麼麻煩呢?我們直接考慮樹上覆蓋。
顯然,在左端點
x +1,右端點
y+1,lc
a(x,
y)-1,fa
lca(
x,y)
-1即可。
於是我們動態開一棵權值線段樹,維護每個點最大值的編號。
操作完成後,對於原圖每個節點,我們把它與兒子節點合併線段樹,對於這題來說,合併就是把個數加起來即可。
這樣合併一次是lo
g2m ,
n 次合併就是nl
og2m
,所以複雜度是優於樹剖的。
#include
#include
#include
#include
#define fo(i,j,k) for(int i=j;i<=k;i++)
#define fd(i,j,k) for(int i=j;i>=k;i--)
#define n 100001
#define m 200001
#define mo 200007
using namespace std;
int to[m],next[m],last[m],num=0;
int d[n],f[n][21];
struct nodetr[n*50];
int a[n];
int h[mo];
int b[n];
int tot=0;
int hash(int
x)void link(int
x,int
y)int cnt=0;
void find(int
x) }
}int lca(int
x,int
y)void change(int v,int l,int r,int
x,int p)
int mid=(l+r)/2;
if(x
<=mid)
else
int i=tr[v].l,j=tr[v].r;
tr[v].mx=max((!i?0:tr[i].mx),(!j?0:tr[j].mx));
}void merge(int v,int vv,int l,int r)
int mid=(l+r)/2;
if(tr[vv].l)
if(tr[vv].r)
int i=tr[v].l,j=tr[v].r;
tr[v].mx=max((!i?0:tr[i].mx),(!j?0:tr[j].mx));
}int findans(int v,int l,int r)
int lyd=0;
void dfs(int
x) }
b[x]=findans(a[x],1,mo-1);
}int main()
find(1);
fo(j,1,20)
fo(i,1,n) f[i][j]=f[f[i][j-1]][j-1];
fo(i,1,n) a[i]=i;
tot=n;
d[0]=-1;
fo(i,1,m)
dfs(1);
fo(i,1,n) printf("%d\n",h[b[i]]);
}
JZOJ 3397 雨天的尾巴
深繪里一直很討厭雨天。灼熱的天氣穿透了前半個夏天,後來一場大雨和隨之而來的洪水,澆滅了一切。雖然深繪里家鄉的小村落對洪水有著頑固的抵抗力,但也倒了幾座老房子,幾棵老樹被連 根拔起,以及田地裡的糧食被弄得一片狼藉。無奈的深繪里和村民們只好等待救濟糧來維生。不過救濟糧的發放方式很特別。首先村落裡的一共有...
雨天的尾巴
acwing連線 bzoj3307 深繪里一直很討厭雨天。灼熱的天氣穿透了前半個夏天,後來一場大雨和隨之而來的洪水,澆滅了一切。雖然深繪里家鄉的小村落對洪水有著頑固的抵抗力,但也倒了幾座老房子,幾棵老樹被連根拔起,以及田地裡的糧食被弄得一片狼藉。無奈的深繪里和村民們只好等待救濟糧來維生。不過救濟糧的...
雨天的尾巴
考試的時候直接扎第一題上了這到題連暴力都沒打出來t t 心路歷程 其實考試時候還是有可能做出來的,當然關鍵在能否想到線段樹合併。當時想到了離散化 很慌沒打出來。樹上差分,lca倍增,當時覺滴倍增很難打,一看n 100000,於是選擇 用向上標記法,然而少了一行 爆零兩行淚。現在看來倍增真是一點不難啊...