日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

BZOJ 2566 xmastree(树分治+multiset)

發(fā)布時間:2023/12/20 编程问答 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 BZOJ 2566 xmastree(树分治+multiset) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

題目鏈接:http://www.lydsy.com:808/JudgeOnline/problem.php?id=2566

題意:一棵有邊權(quán)的樹。結(jié)點有顏色。每次修改一個點的顏色。求每次修改后所有同色結(jié)點的最近距離。

思路:整體是樹分治的方法。其實,分治之后,我們可以理解為重構(gòu)了這棵樹,使得最大深度最小。這棵樹的每個結(jié)點對于每種顏色保存兩個值。一個是該種顏色的所有點到該結(jié)點的距離,設這些距離中最小的兩個值Min1,Min2,那么Min1+Min2可看做是經(jīng)過當前結(jié)點的這種顏色的兩個結(jié)點的最近距離,另外,還要保存其他孩子中關于這種顏色的最小值。所有這些最小值的最小值和Min1+Min2再取最小值就是以該節(jié)點為根的樹的這種顏色的最小值。這些最小值用multiset維護。

另外,結(jié)點維護所有同種顏色的距離時也用multiset維護。

對于修改操作,設u節(jié)點的顏色由c1變?yōu)閏2,分兩步完成,第一步刪除u結(jié)點的c1,第二步加入u結(jié)點的c2。

兩種操作類似,都是從當前結(jié)點一直向上更新。細節(jié)比較多。

multiset直接刪除一個值時是將所有這個值都刪掉,只刪除一個的話要用指針。

const int M=12005;struct node {int v,w,next; };node edges[M<<1]; int head[M],eNum;void add(int u,int v,int w) {edges[eNum].v=v;edges[eNum].w=w;edges[eNum].next=head[u];head[u]=eNum++; }int n,m; int color[M];int fa[M][20]; int d[M],dep[M];int visit[M];queue<int> Q;void init() {Q.push(1);visit[1]=1;while(!Q.empty()){int u=Q.front();Q.pop();for(int i=head[u];i!=-1;i=edges[i].next){int v=edges[i].v;int w=edges[i].w;if(!visit[v]){fa[v][0]=u;d[v]=d[u]+w;dep[v]=dep[u]+1;Q.push(v);visit[v]=1;}}}for(int i=1;i<20;i++) for(int j=1;j<=n;j++){fa[j][i]=fa[fa[j][i-1]][i-1];} }int calLca(int u,int v) {if(dep[u]<dep[v]) swap(u,v);int x=dep[u]-dep[v];for(int i=0;i<20;i++) if(x&(1<<i)) u=fa[u][i];if(u==v) return u;for(int i=19;i>=0;i--){if(fa[u][i]&&fa[v][i]&&fa[u][i]!=fa[v][i]){u=fa[u][i];v=fa[v][i];}}return fa[u][0]; }int calDis(int u,int v) {int lca=calLca(u,v);return d[u]+d[v]-d[lca]*2; }int sonNum[M];int nodeSum;int arr[M],arrNum;void dfs(int u,int pre) {arr[++arrNum]=u;nodeSum++;sonNum[u]=1;for(int i=head[u];i!=-1;i=edges[i].next){int v=edges[i].v;if(v!=pre&&!visit[v]){dfs(v,u);sonNum[u]+=sonNum[v];}} }int calCenter(int u) {nodeSum=0; arrNum=0;dfs(u,0);int ans=u,Min=INF;for(int i=1;i<=arrNum;i++){int u=arr[i];int tmp=max(sonNum[u],nodeSum-sonNum[u]);if(tmp<Min) Min=tmp,ans=u;}return ans; }struct NODE {multiset<int> S,p;int getAns(){if(p.size()<2) return INF;int Min1=*p.begin();multiset<int>::iterator it=p.begin();it++;int Min2=*it;return Min1+Min2;}void del(int x){p.erase(p.find(x));} };map<int,NODE> mp[M]; map<int,NODE>::iterator it;int inq[M],KK; int dis[M]; int parent[M];int DFS(int root) {root=calCenter(root);Q.push(root);KK++;inq[root]=KK;dis[root]=0;while(!Q.empty()){int u=Q.front();Q.pop();int c=color[u];if(mp[root].count(c)){mp[root][c].p.insert(dis[u]);}else{NODE tmp;tmp.p.insert(dis[u]);mp[root][c]=tmp;}for(int i=head[u];i!=-1;i=edges[i].next){int v=edges[i].v;int w=edges[i].w;if(!visit[v]&&KK!=inq[v]){inq[v]=KK;dis[v]=dis[u]+w;Q.push(v);}}}for(it=mp[root].begin();it!=mp[root].end();it++){NODE tmp=it->second;it->second.S.insert(tmp.getAns());}visit[root]=1;for(int i=head[root];i!=-1;i=edges[i].next){int v=edges[i].v;if(!visit[v]){v=DFS(v);for(it=mp[v].begin();it!=mp[v].end();it++){int c=it->first;int w=*(it->second.S.begin());mp[root][c].S.insert(w);}parent[v]=root;}}return root; }int root;multiset<int> SS;void Add(int u,int c,int dis) {if(mp[u].count(c)){mp[u][c].p.insert(dis);}else{NODE tmp;tmp.p.insert(dis);mp[u][c]=tmp;} }int st[M],stTop;void setDel(multiset<int> &S,int x) {multiset<int>::iterator it=S.find(x);if(it!=S.end()) S.erase(it); }void del(int u,int c) {setDel(SS,*mp[root][c].S.begin());int curNode=u;stTop=0;while(curNode) st[++stTop]=curNode,curNode=parent[curNode];for(int i=stTop;i>1;i--){int u=st[i];int v=st[i-1];setDel(mp[u][c].S,*mp[v][c].S.begin());}curNode=u;while(curNode){int p=parent[curNode];setDel(mp[curNode][c].S,mp[curNode][c].getAns());mp[curNode][c].del(calDis(u,curNode));mp[curNode][c].S.insert(mp[curNode][c].getAns());if(p){mp[p][c].S.insert(*(mp[curNode][c].S.begin()));}curNode=p;}SS.insert(*mp[root][c].S.begin()); }void upd(int u,int c) {if(mp[root].count(c)){setDel(SS,*mp[root][c].S.begin());}int curNode=u;stTop=0;while(curNode) st[++stTop]=curNode,curNode=parent[curNode];for(int i=stTop;i>1;i--){int u=st[i];int v=st[i-1];if(!mp[v].count(c)) break;setDel(mp[u][c].S,*mp[v][c].S.begin());}for(int i=1;i<=stTop;i++){int u=st[i];if(mp[u].count(c)){setDel(mp[u][c].S,mp[u][c].getAns());}}curNode=u;while(curNode){Add(curNode,c,calDis(u,curNode));mp[curNode][c].S.insert(mp[curNode][c].getAns());int p=parent[curNode];if(p){mp[p][c].S.insert(*(mp[curNode][c].S.begin()));}curNode=p;}SS.insert(*mp[root][c].S.begin()); }void change(int u,int c) {if(color[u]==c) return;del(u,color[u]);upd(u,c);color[u]=c; }int main() {n=myInt();for(int i=1;i<=n;i++) color[i]=myInt();clr(head,-1);for(int i=1;i<n;i++){int u=myInt();int v=myInt();int w=myInt();add(u,v,w);add(v,u,w);}init();clr(visit,0);root=DFS(1);for(it=mp[root].begin();it!=mp[root].end();it++){SS.insert(*(it->second.S.begin()));}int minDis=*SS.begin();printf("%d\n",minDis==INF?-1:minDis);m=myInt();while(m--){int x=myInt();int y=myInt();change(x,y);minDis=*SS.begin();printf("%d\n",minDis==INF?-1:minDis);} }

  

?

總結(jié)

以上是生活随笔為你收集整理的BZOJ 2566 xmastree(树分治+multiset)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

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