日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) >

HYSBZ - 2243染色——树链剖分+线段树建树技巧

發(fā)布時(shí)間:2023/11/30 42 豆豆
生活随笔 收集整理的這篇文章主要介紹了 HYSBZ - 2243染色——树链剖分+线段树建树技巧 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

【題目描述】
HYSBZ - 2243染色

【題目分析】
我一直沒(méi)有看清楚題,以為求的是路徑上出現(xiàn)顏色的種類,然后就寫(xiě)了一個(gè)區(qū)間染色的線段樹(shù)進(jìn)行維護(hù),過(guò)樣例的時(shí)候才發(fā)現(xiàn)題讀錯(cuò)了,人家要求的是路徑上出現(xiàn)的顏色段,所以顏色的種類不重要,重要的是每一段每一段。理所當(dāng)然,我們應(yīng)該用線段樹(shù)維護(hù)所在區(qū)間有多少段。但是左右區(qū)間上傳的時(shí)候如果邊界顏色相同(左節(jié)點(diǎn)的右邊界和右節(jié)點(diǎn)的左邊界),那么區(qū)間個(gè)數(shù)應(yīng)該減一。為此,我們還必須維護(hù)每個(gè)區(qū)間左邊界和右邊界分別是什么顏色以方便查詢和上傳。因?yàn)轭}目是區(qū)間修改,所以我們還要用lazy標(biāo)記。(用lazy標(biāo)記的時(shí)候要時(shí)時(shí)記得標(biāo)記下傳,就是因?yàn)閱吸c(diǎn)查詢的時(shí)候忘記要標(biāo)記下傳wa了一下午)
因?yàn)樵跇?shù)上,所以我們不僅僅需要判斷線段樹(shù)區(qū)間合并的時(shí)候左右端點(diǎn)顏色是否相同,還要判斷每條鏈頂和鏈頂?shù)母腹?jié)點(diǎn)的顏色是否相同,如果相同答案減一。(每條鏈都在向鏈頂合并)

【AC代碼】

#include<iostream> #include<cstdio> #include<vector> #include<cmath> #include<cstring> #include<algorithm> #include<climits>using namespace std;const int MAXN=100005; //時(shí)刻注意數(shù)據(jù)范圍 vector<int>g[MAXN]; int fa[MAXN],A[MAXN],val[MAXN],color[MAXN],pos[MAXN]; bool check[MAXN]; int siz[MAXN],son[MAXN],h[MAXN],top[MAXN]; int cnt=0,n,m; int num[MAXN<<2],lazy[MAXN<<2]; int lc[MAXN<<2],rc[MAXN<<2];void dfs1(int u,int f) {int i,v;siz[u]=1;son[u]=0;fa[u]=f;h[u]=h[f]+1;for(i=0;i<g[u].size();i++){v=g[u][i];if(v!=f){dfs1(v,u);siz[u]+=siz[v];if(siz[son[u]]<siz[v]) son[u]=v;}} } void dfs2(int u,int f,int k) {int i,v;top[u]=k;pos[u]=++cnt;color[cnt]=val[u];if(son[u]) dfs2(son[u],u,k);for(i=0;i<g[u].size();i++){v=g[u][i];if(v!=f&&v!=son[u]) dfs2(v,u,v);} }void pushup(int k) {num[k]=num[k<<1]+num[k<<1|1];if(rc[k<<1]==lc[k<<1|1]) num[k]--; //如果左右區(qū)間的連接處顏色相同則答案減一lc[k]=lc[k<<1]; rc[k]=rc[k<<1|1]; }void build(int k,int l,int r) {if(l==r){num[k]=1;lc[k]=rc[k]=color[l];return;}int mid=(l+r)>>1;build(k<<1,l,mid);build(k<<1|1,mid+1,r);pushup(k); }void pushdown(int k) {if(lazy[k]){lazy[k<<1]=lazy[k<<1|1]=lazy[k];lc[k<<1]=lc[k<<1|1]=lazy[k];rc[k<<1]=rc[k<<1|1]=lazy[k];num[k<<1]=num[k<<1|1]=1;lazy[k]=0;} }void ColorChange(int k,int l,int r,int L,int R,int v) {if(l>=L && r<=R){num[k]=1; lazy[k]=v;lc[k]=v; rc[k]=v;return;}int mid=(l+r)>>1;pushdown(k);if(L<=mid) ColorChange(k<<1,l,mid,L,R,v);if(R>mid) ColorChange(k<<1|1,mid+1,r,L,R,v);pushup(k); }int QueryInterval(int k,int l,int r,int L,int R) {if(L<=l && r<=R){return num[k];}int mid=(l+r)/2;pushdown(k);int ret=0;if(R<=mid) return QueryInterval(k<<1,l,mid,L,R);else if(L>mid) return QueryInterval(k<<1|1,mid+1,r,L,R); //這里必須這樣寫(xiě),因?yàn)橐紤]是否存在區(qū)間合并ret+=QueryInterval(k<<1,l,mid,L,R);ret+=QueryInterval(k<<1|1,mid+1,r,L,R);if(rc[k<<1]==lc[k<<1|1]) ret--;return ret; }int QueryPointColor(int k,int l,int r,int x) {if(l==r && l==x){return lc[k];}pushdown(k); //因?yàn)檫@里忘記了.wocint mid=(l+r)>>1;if(x<=mid) return QueryPointColor(k<<1,l,mid,x);else return QueryPointColor(k<<1|1,mid+1,r,x); }int Findnum(int u,int v) {memset(check,0,sizeof(check));int ans=0;while(top[u]!=top[v]){if(h[top[u]]<h[top[v]]) swap(u,v);ans+=QueryInterval(1,1,n,pos[top[u]],pos[u]);//printf("ans=%d\n",ans);//printf("QueryPointColor(1,1,n,pos[%d])=%d\nQueryPointColor(1,1,n,pos[%d])=%d\n",top[u],QueryPointColor(1,1,n,pos[top[u]]),fa[top[u]],QueryPointColor(1,1,n,pos[fa[top[u]]]));if(QueryPointColor(1,1,n,pos[top[u]]) == QueryPointColor(1,1,n,pos[fa[top[u]]])) //考慮鏈與鏈的合并ans--;u=fa[top[u]];}if(h[u]<h[v]) swap(u,v);ans+=QueryInterval(1,1,n,pos[v],pos[u]);//printf("ans=%d\n",ans);return ans; }void update(int u,int v,int w) {while(top[u]!=top[v]){if(h[top[u]]<h[top[v]]) swap(u,v);ColorChange(1,1,n,pos[top[u]],pos[u],w);u=fa[top[u]];}if(h[u]<h[v]) swap(u,v);ColorChange(1,1,n,pos[v],pos[u],w); }int main() {int a,b,c;char s[10];scanf("%d%d",&n,&m);for(int i=1;i<=n;i++) scanf("%d",&val[i]);for(int i=1;i<n;i++){scanf("%d%d",&a,&b);g[a].push_back(b);g[b].push_back(a);}dfs1(1,0);dfs2(1,0,1);build(1,1,n);while(m--){scanf("%s",s);if(s[0]=='C'){scanf("%d%d%d",&a,&b,&c);update(a,b,c);}else if(s[0]=='Q') {scanf("%d%d",&a,&b);printf("%d\n",Findnum(a,b));}}return 0; }

總結(jié)

以上是生活随笔為你收集整理的HYSBZ - 2243染色——树链剖分+线段树建树技巧的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。