gym 102059A 樹鏈剖分後odt維護區間

2022-05-16 21:36:10 字數 1682 閱讀 5697

題意

一棵樹多次修改,每次修改乙個點到根的所有邊的顏色,並詢問現在有哪些顏色染了恰好$m$條邊

題解:稍加思考可以知道,從某個點到根節點的顏色數,均攤複雜度很低,因此,可以考慮珂朵莉樹維護重鏈剖分

這裡也記錄一下珂朵莉樹的**

**:

#include#define endl '\n'

#define ll long long

#define ull unsigned long long

#define fi first

#define se second

#define pii pair#define all(x) x.begin(),x.end()

#define io ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)

#define rep(ii,a,b) for(int ii=a;ii<=b;++ii)

#define per(ii,a,b) for(int ii=b;ii>=a;--ii)

#define forn(ii,x) for(int ii=head[x];ii;ii=edge[ii].next)

using namespace std;

const int maxn=2e5+20,maxm=2e6+10;

const int inf=0x3f3f3f3f;

const ll mod=1e9+7;

int casn,n,m,k,col[maxn],ans[maxn];

class odtree);

if(it==nodes.end()||(it->l)>pos||(it->r)==pos) return ;

int l=it->l,r=it->r,c=it->c;

nodes.erase(it);nodes.insert();nodes.insert();

} void update(int l,int r,int c));

if(it==nodes.end()||(it->l)>r) break;

if(it->c)

nodes.erase(it);

}--ans[col[c]];col[c]+=r-l+1;++ans[col[c]];

nodes.insert();

}}tree;

namespace chainedge[maxn<<1];

int head[maxn],nume,mp[maxn];

int ltop[maxn],fa[maxn],deep[maxn];

int sz[maxn],remp[maxn],son[maxn],cnt;

inline void addedge(int a,int b);head[a]=nume;}

void init()

void dfs1(int now,int pre,int d)

}} void dfs2(int now,int pre,int sp)

} void gao(int st=1)

void update(int now,int c)

}};int main()

ans[0]=m;

chain::gao();

tree.nodes.insert();

while(k--)

return 0;

}

樹鏈剖分剖後感

處理以節點x為根的整個子樹 用線段樹處理 pos x pos x siz x 1 即可 查詢節點x和節點y的lca 最近公共祖先 將兩點不斷向上挪動並處理,直到兩點的top相同,deep小的點即是最近公共祖先 處理節點x到節點y的路徑上的點 將兩點不斷向上挪動並處理,直到兩點的top相同,最後用線段...

樹鏈剖分 樹鏈剖分講解

好了,這樣我們就成功解決了對樹上修改查詢邊權或點的問題。下面放上 vector v maxn int size maxn dep maxn val maxn id maxn hson maxn top maxn fa maxn 定義 int edge 1,num 1 struct tree e ma...

Gym 101908L 樹鏈剖分裸題

題目大意 一棵n nn個點的樹上,查詢a aa b bb,c cc d dd兩段路徑公共的點的個數。解題思路 讀完題就感覺是樹鏈剖分的裸題呀 把每個點的值初始化為0 00,對於每次詢問,把a aa b bb這條路徑的值 1 1 1,查詢c cc d dd的區間和,再把a aa b bb這條路徑的值 ...