雨天的尾巴

2022-05-06 20:42:12 字數 3142 閱讀 3882

考試的時候直接扎第一題上了這到題連暴力都沒打出來t_t;

心路歷程:

其實考試時候還是有可能做出來的,當然關鍵在能否想到線段樹合併。

當時想到了離散化(很慌沒打出來。。。),樹上差分,lca倍增,當時覺滴倍增很難打,一看n<100000,於是選擇

用向上標記法,然而少了一行**,,,,爆零兩行淚。。。

現在看來倍增真是一點不難啊好打有好用,所以不要有為難情緒,剛就完了。(平日板子要多打記熟啊)

之所以沒想到線段樹合併是因為當時真的沒有透徹理解,

所以新知識點還是要知道它能幹什麼,知道它的用處。

離散化用來乾掉1->10^9,考試的時候真的傻認為要是有10^9種不就完了嗎,,,然後發現忘了還有m次操作這東東,所以z離散化後len最大也就m個卡掉了很多

以前乙個物品的題直接dfs,lca樹上差分就行,現在有10^9個(離散後10^5個),空間時間不可能乙個乙個去維護所以 得用線段樹合併。

每個點有很多資訊所以權值線段樹用來優化空間(當然也能優化時間),對每個點動態開樹插入和刪除(lca,f[lca]),最後dfs,父親合併兒子。

所以需維護區間的maxcnt以及其id,在merge時就需要多傳一下l,r(1,len),如果l==r更新maxx值和id,需要注意的是如果maxx<=0,id乾成0(題目要求)。

sd錯誤:merge時忘了加上root[x]=merge,如果root[x]=0,就會...炸。還有空間沒開夠得開到maxn*50。

優化:插入時如果lca==x||lca==y,那就插入了一次刪了一次所以乾脆不插入。。。

#include#include

#include

#include

using

namespace

std;

const

int maxn=100050

;bool

mark[maxn];

intn,m,t,ans[maxn],len;

int kpx[maxn],kpy[maxn],kpz[maxn],turn[maxn];//

離線離散化

int deep[maxn],f[maxn][20];//

倍增lca

int sz,root[maxn],cnt[maxn*50],lc[maxn*50],rc[maxn*50],maxx[maxn*50],num[maxn*50];//

線段樹int head[maxn],cntn=1

;struct

nodeline[maxn*2

];void add(int x,int

y)void dfs(int

x) }

}int ask(int x,int

y) }

return f[x][0];}

void insert(int &root,int l,int r,int

x)

int mid=(l+r)/2

;

if(x<=mid) insert(lc[root],l,mid,x);

else insert(rc[root],mid+1

,r,x);

if(maxx[lc[root]]>=maxx[rc[root]]) maxx[root]=maxx[lc[root]],num[root]=num[lc[root]];

else maxx[root]=maxx[rc[root]],num[root]=num[rc[root]];

}void decrease(int &root,int l,int r,int

x)

int mid=(l+r)/2

;

if(x<=mid) decrease(lc[root],l,mid,x);

else decrease(rc[root],mid+1

,r,x);

if(maxx[lc[root]]>=maxx[rc[root]]) maxx[root]=maxx[lc[root]],num[root]=num[lc[root]];

else maxx[root]=maxx[rc[root]],num[root]=num[rc[root]];

}int merge(int x,int y,int l,int

r)

int mid=(l+r)/2

; lc[x]=merge(lc[x],lc[y],l,mid);

rc[x]=merge(rc[x],rc[y],mid+1

,r);

if(maxx[lc[x]]>=maxx[rc[x]]) maxx[x]=maxx[lc[x]],num[x]=num[lc[x]];

else maxx[x]=maxx[rc[x]],num[x]=num[rc[x]];

returnx;}

void dfst(int

x) }

ans[x]=turn[num[root[x]]];

}int

main()

deep[

1]=1

; mark[

1]=1

; dfs(1);

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

sort(turn+1,turn+1+m);

len=unique(turn+1,turn+1+m)-(turn+1

);

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

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

if(x==kpy[i])

insert(root[ kpx[i] ],

1,len,kpz[i]);

insert(root[ kpy[i] ],

1,len,kpz[i]);

decrease(root[x],

1,len,kpz[i]);

decrease(root[ f[x][

0] ],1

,len,kpz[i]);

}memset(mark,

0,sizeof

(mark));

mark[

1]=1

; dfst(1);

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

}

雨天的尾巴

acwing連線 bzoj3307 深繪里一直很討厭雨天。灼熱的天氣穿透了前半個夏天,後來一場大雨和隨之而來的洪水,澆滅了一切。雖然深繪里家鄉的小村落對洪水有著頑固的抵抗力,但也倒了幾座老房子,幾棵老樹被連根拔起,以及田地裡的糧食被弄得一片狼藉。無奈的深繪里和村民們只好等待救濟糧來維生。不過救濟糧的...

雨天的尾巴題目解析

考試的時候直接扎第一題上了這到題連暴力都沒打出來t t 心路歷程 其實考試時候還是有可能做出來的,當然關鍵在能否想到線段樹合併。當時想到了離散化 很慌沒打出來。樹上差分,lca倍增,當時覺滴倍增很難打,一看n 100000,於是選擇 用向上標記法,然而少了一行 爆零兩行淚。現在看來倍增真是一點不難啊...

bzoj3307 雨天的尾巴

time limit 10 sec memory limit 128 mb submit 258 solved 121 submit status discuss n個點,形成乙個樹狀結構。有m次發放,每次選擇兩個點x,y 對於x到y的路徑上 含x,y 每個點發一袋z型別的物品。完成 所有發放後,每...