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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

bzoj 3924 幻想乡战略游戏

發布時間:2023/11/29 编程问答 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 bzoj 3924 幻想乡战略游戏 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

題目大意:
有邊權點權的樹,動態修改點權
每次修改后求帶權重心x (\(minimize\) \(S=\sum_i val[i]*dist[x][i]\))
分析:
從暴力找突破口:
對于邊x,y,設長度為len,切斷后x半邊樹權值和為\(w_1\),y半邊樹為\(w_2\)
若從重心從x轉到到y,則\(S+w_1*len-w_2*len\)
y比x優當且僅當\(w_2>w_1\)
設當前根為root,若root的一兒子x,滿足\(w_x>w_{root}-w_x\),則x更優,且可以證明\(w_x>\frac {w_{root}} 2\),即不會存在第二個兒子y也比root優
做法:
暴力做法深度無保證,但\(w_x>w_{root}-w_x\)可以確定答案在x子樹
我們用點分治樹保證深度
新的問題:點分治樹怎么求w
對于邊x,y,設x半邊樹中所有點到x距離為\(d_1\),y半邊樹中所有點到y距離為\(d_2\)
所有點到x距離為\(d_1+d_2+w_2*len\)
所有點到y距離為\(d_1+d_2+w_1*len\)
可以了啊,這就是動態點分治模板了
詢問復雜度\(nlog^2n\)
==============================================================================================
后來信息隊一位善于創新的大神想到了nlogn的方法
x為rt,y為點分兒子時
x在上則兩邊權值和分別為w(y)和w(root)-w(y)
y在上則兩邊權值和分別為w(root)-w(x)+w(y)和w(x)-w(y)
乍一看非常正確,用rmq求個lca就可以O(1)判上下,超簡便維護
但如果如圖 :

兜來兜去的圖發現bug多多
吸取經驗

#include <cstdio> #include <cstdlib> #include <cstring> #include <algorithm> #include <cmath> #include <cctype> using namespace std; typedef long long LL; const int M=100007; const int N=M*20*2; inline int rd(){int x=0;bool f=1;char c=getchar();for(;!isdigit(c);c=getchar())if(c=='-')f=0;for(;isdigit(c);c=getchar())x=x*10+c-48;return f?x:-x; }int n,m;int g[M],te; struct edge{int y,next;LL d; }e[M<<1]; void addedge(int x,int y,LL d){e[++te].y=y;e[te].d=d;e[te].next=g[x];g[x]=te; }int fir[M],td; struct down{int y;//點分兒子int son;//親兒子int next; }dw[M]; void adddw(int x,int y,int son){dw[++td].y=y;dw[td].son=son;dw[td].next=fir[x];fir[x]=td; }int hd[M],tu; struct uppp{int all,sub,next;LL dis; }up[N]; void addup(int x,int all,int sub,LL dis){up[++tu].all=all;up[tu].sub=sub;up[tu].dis=dis;up[tu].next=hd[x];hd[x]=tu; }struct node{LL sum,val; }a[M<<1]; int idrt,idsub,nw;int sz[M],vis[M]; int mi,size,rt,root;void getsz(int x,int fa){sz[x]=1;int p,y;for(p=g[x];p;p=e[p].next)if(!vis[y=e[p].y]&&y!=fa){getsz(y,x);sz[x]+=sz[y];} }void getrt(int x,int fa){int f,p,y;f=size-sz[x];for(p=g[x];p;p=e[p].next)if(!vis[y=e[p].y]&&y!=fa){getrt(y,x);f=max(f,sz[y]);}if(f<mi) mi=f,rt=x; }void dfs(int x,int fa,LL dis){addup(x,idrt,idsub,dis);int p,y;for(p=g[x];p;p=e[p].next)if(!vis[y=e[p].y]&&y!=fa){dfs(y,x,dis+e[p].d);} }void work(int frm,int drt){getsz(frm,0);mi=size=sz[frm];getrt(frm,0);int x=rt,p,y;vis[x]=1;idrt=++nw;addup(x,idrt,-1,0);if(drt) adddw(drt,x,frm);else root=x;for(p=g[x];p;p=e[p].next)if(!vis[y=e[p].y]){idsub=++nw;dfs(y,x,e[p].d);}for(p=g[x];p;p=e[p].next)if(!vis[y=e[p].y]) work(y,x); }void update(int x,LL y){int p;for(p=hd[x];p;p=up[p].next){a[up[p].all].val+=y;a[up[p].all].sum+=y*up[p].dis;if(up[p].sub!=-1){a[up[p].sub].val+=y;a[up[p].sub].sum+=y*up[p].dis;}} }LL get(int x){LL res=0;int p;for(p=hd[x];p;p=up[p].next){res+=a[up[p].all].sum;res+=a[up[p].all].val*up[p].dis;if(up[p].sub!=-1){res-=a[up[p].sub].sum;res-=a[up[p].sub].val*up[p].dis;}}return res; }int anst; void find(int x){int p,y,bb=1;for(p=fir[x];p;p=dw[p].next)if(get(x)>=get(dw[p].son)){bb=0;find(dw[p].y);break;}if(bb) anst=x; }int main(){int i,x,y,z;n=rd();m=rd();for(i=1;i<n;i++){x=rd(),y=rd(),z=rd();addedge(x,y,z);addedge(y,x,z);}work(1,0);for(i=1;i<=m;i++){x=rd(),y=rd();update(x,y);find(root);printf("%lld\n",get(anst));}return 0; }

轉載于:https://www.cnblogs.com/acha/p/6283355.html

創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎

總結

以上是生活随笔為你收集整理的bzoj 3924 幻想乡战略游戏的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。