題意
一棵樹多次修改,每次修改乙個點到根的所有邊的顏色,並詢問現在有哪些顏色染了恰好$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這條路徑的值 ...