為啥說是小結。。這辣雞題我寫了兩天。
(順帶其中參觀了一下scoi的大新聞)
這題思路首先是樹剖,剖出來之後,考慮對於每個點維護乙個d1,d2,表示從這個點往下走,不經過自己所在重鏈的邊,到達乙個黑點的最長路徑和次長路徑。如果下面黑點不足就是-inf了。
處理出來之後,對於一條鏈,線段樹維護這麼幾個值,
lv:表示其中乙個黑點走到左端點的最長距離
rv:同上,走到右端點
v:其中兩個黑點的最長路徑。
然後處理乙個樹上路徑字首和,sum[i]表示根到i的距離。
(lc代表左兒子,rc代表右兒子,窩用的是指標可能會有點鬼畜)
(suml表示左兒子那個區間的路徑和,sumr表示右兒子路徑和,l表示中間那條邊長度)
轉移的話
lv=max(lc->lv,suml+l+rc->lc)
rv=max(rc->rv,sumr+l+lc->rv)
v=max
//是不是覺得跟最大連續子段和一毛一樣呀
對於邊界,也就是乙個點的情況
如果是黑點 lv=rv=max(0,d1)
否則 lv=rv=d1
如果是黑點 v=max(d1,d1+d2)
否則 v=d1+d2
然後就維護好了。
考慮來怎麼維護這個d啊,
『 我是這樣做的啊,solve一條鏈的方法是,從上往下遍歷鏈的每個點u,然後solve u可以遍歷到的非當前鏈節點v,然後這個函式返回這條鏈的lv(就是上面提到的lv),然後把lv加上w(u,v)扔進堆,最後取前兩個。
然後也維護好了啊。
怎麼回答呢,,我當時比較zz,把每條鏈的v扔進乙個堆然後query的時候直接取堆頂。
修改怎麼搞,,先找到點所在的鏈,線段樹上update一下這條鏈的v,然後往上爬直到根節點。因為下面的節點顏色變了,上面的節點的d1,d2要重算,幸運的是需要重算的鏈的數量不超過logn條,一次update複雜度為logn,機智的同學會發現為了維護新的d1,d2可能需要刪除之前的一些資訊(畢竟有點的顏色變了),需要從堆裡刪去乙個值,然後就變成用set維護了(也許常數比較大)
這題細節比較多強烈建議跟暴力拍。不過不要像我一樣,暴力陣列開小了,還在疑惑為什麼一拍大資料就wa。
(有點像wrs講的維護資訊的題目,線段樹主要就是能維護資訊,資訊能合併,於是可以定義data來表示資訊,過載+或者寫乙個merge函式,在up和query的時候都會用到(這個題調的欲仙欲死,好久沒寫4k+**咯))
//qwsin
#include
#include
#include
#include
#include
#include
using
namespace
std;
const
int maxn=100000+10;
const
int maxm=200000+10;
template
struct cmp
};multiset
>topval,f[maxn];
struct edge}e[maxm];
int first[maxn],next[maxm],ecnt;
inline
void add_edge(int u,int v,int w)
int sum[maxn];//樹上路徑字首和
struct data
inline
void init()
};inline data add(const data &a,const data &b,int l,int suml,int sumr)
struct node
}*root;
#define mid ((l+r)>>1)
int n,iid[maxn],col[maxn];
int sz[maxn],fa[maxn],tid[maxn],hv[maxn],top[maxn],dn[maxn],dep[maxn];
const
int inf=1
<<28;
inline
void work(node* p,int u)//用f[u]的資訊更新u單點的資訊
void build(node* &p,int l,int r)
if(pos<=mid) updata(p->lc,l,mid,pos);
else updata(p->rc,mid+1,r,pos);
p->t=add(p->lc->t , p->rc->t , sum[iid[mid+1]]-sum[iid[mid]],sum[iid[mid]]-sum[iid[l]],sum[iid[r]]-sum[iid[mid+1]]);
}data query(node* p,int l,int r,int l,int r)
void dfs1(int u,int pre,int dis=0)
}}int node_cnt;
void dfs2(int u,int top)
int cntb;
inline
void output(multiset
>&s)
puts("\n");
}inline
int solve_top(int top)//計算以top為top的重鏈
updata(root,1,n,tid[u]);
if(sz[u]==1) break;
}data ret=query(root,1,n,tid[top],tid[dn[top]]);
topval.insert(ret.v);
// output(topval);
return ret.lv;
}inline
void init_data()
for(int i=1;i<=n;++i) col[i]=1;cntb=n;
dfs1(1,1);dfs2(1,1);
build(root,1,n);
solve_top(1);
// output(topval);
}inline
int query()
inline data query(int pos)
inline
void updata(int pos)
inline
void solve()
printf("%d\n",query());
}else
}}int main()
我是這樣寫文字輪播的
功能點 文字無縫輪播 不要在意為什麼在移動端還會有這樣的需求 當一說到文字無縫滾動時,大家最先想到的是marquee,但是已經好久沒有接觸這個標籤了,w3c也不對其進行 維護了,並且還有最後必須等到全部滾動完畢才會再次滾動,並且對於rem布局採用基於px的滾動體驗會非常的 差等等。第二個想到的是採用...
我是如何寫部落格的 轉
本文主要介紹了如何使用 restructuredtext 簡稱為rest 來寫部落格,並且介紹了使用 google code 來管理部落格原始檔的方法。內容如下 contents 摘要 使用restructuredtext作為格式化文件的原始檔 使用google code作為文件的源 伺服器 參考資...
我是怎麼寫JavaScript框架的(一)
以前大三的時候寫的乙個小框架,仿jquery鏈式結構,純屬練手,大牛勿噴。當時還把jq的原始碼全部列印下來 因為在電腦上看不方便做筆記 7600 行 300 頁a4紙,對照著看別人是怎麼寫的。還好乙個長我一屆的學長當時比較閒,我說我想讀jq 他也沒讀過,就找來上兩屆的學長以前練手寫的小框架進行學習。...