QTREE4小結 我寫的是樹剖

2021-07-30 12:08:47 字數 3274 閱讀 4356

為啥說是小結。。這辣雞題我寫了兩天。

(順帶其中參觀了一下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 他也沒讀過,就找來上兩屆的學長以前練手寫的小框架進行學習。...