HDU D Tree [点分治]
生活随笔
收集整理的這篇文章主要介紹了
HDU D Tree [点分治]
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
傳送門
題意:找路徑積$\mod 1e6+3 = k$的字典序最小點對
?
作為一個點分治蒟蒻,寫這道題花了兩節課....
顯然只要開一個桶$c[i]$記錄當前路徑積為$i$的最小點
然后處理一個子樹時一個個子樹遍歷更新答案再更新$c$就行了
最后再把$c$復原
可以用一個棧記下更改過的$c$,但貌似比在遍歷一遍樹更慢?
然后注意更新和復原$c[w[u]]$
好了回教室上數學課啦
?
#pragma comment(linker,"/STACK:102400000,102400000") #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace std; typedef long long ll; const int N=1e5+5,M=1e6+5,P=1e6+3,INF=1e9; inline int read(){char c=getchar();int x=0,f=1;while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}return x*f; } int n;ll k,w[N]; struct edge{int v,ne; }e[N<<1]; int h[N],cnt; inline void ins(int u,int v){cnt++;e[cnt].v=v;e[cnt].ne=h[u];h[u]=cnt;cnt++;e[cnt].v=u;e[cnt].ne=h[v];h[v]=cnt; } int inv[M]; void iniInv(){inv[1]=1;for(int i=2;i<P;i++)inv[i]=(ll)(P-P/i)*inv[P%i]%P; }int size[N],f[N],vis[N],root,allSize; void dfsRt(int u,int fa){size[u]=1;f[u]=0;for(int i=h[u];i;i=e[i].ne){int v=e[i].v;if(vis[v]||v==fa) continue;dfsRt(v,u);size[u]+=size[v];f[u]=max(f[u],size[v]);}f[u]=max(f[u],allSize-size[u]);if(f[u]<f[root]) root=u; } int c[M],ans[2]; int st[N],top; void dfsDee(int u,int fa,int now){if(!c[now]) c[now]=u;//,st[++top]=now;else c[now]=min(c[now],u);for(int i=h[u];i;i=e[i].ne){int v=e[i].v;if(!vis[v]&&v!=fa) dfsDee(v,u,now*w[v]%P);} } void dfsAns(int u,int fa,int now){int x=c[k*inv[now]%P],y=u;if(x){if(x>y) swap(x,y);if(x<ans[0]||(x==ans[0]&&y<ans[1])) ans[0]=x,ans[1]=y;}for(int i=h[u];i;i=e[i].ne){int v=e[i].v;if(!vis[v]&&v!=fa) dfsAns(v,u,now*w[v]%P);} } void dfsRec(int u,int fa,int now){c[now]=0;for(int i=h[u];i;i=e[i].ne){int v=e[i].v;if(!vis[v]&&v!=fa) dfsRec(v,u,now*w[v]%P);} } void dfsSol(int u){vis[u]=1;c[w[u]]=u;for(int i=h[u];i;i=e[i].ne){int v=e[i].v;if(!vis[v]){dfsAns(v,u,w[v]);dfsDee(v,u,w[u]*w[v]%P);}}//while(top) c[st[top]]=0,top--;for(int i=h[u];i;i=e[i].ne) if(!vis[e[i].v]) dfsRec(e[i].v,u,w[u]*w[e[i].v]%P);c[w[u]]=0;for(int i=h[u];i;i=e[i].ne){int v=e[i].v;if(!vis[v]){root=0;allSize=size[v];dfsRt(v,0);dfsSol(root);}} } int main(){freopen("in","r",stdin);iniInv();while(scanf("%d%lld",&n,&k)!=EOF){memset(vis,0,sizeof(vis));cnt=0;memset(h,0,sizeof(h));memset(c,0,sizeof(c));for(int i=1;i<=n;i++) w[i]=read();for(int i=1;i<=n-1;i++) ins(read(),read());ans[0]=ans[1]=INF;f[0]=INF;root=0;allSize=n;dfsRt(1,0);dfsSol(root);if(ans[0]!=INF) printf("%d %d\n",ans[0],ans[1]);else puts("No solution");} }?
轉載于:https://www.cnblogs.com/candy99/p/6494634.html
總結
以上是生活随笔為你收集整理的HDU D Tree [点分治]的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 第五章 作用域闭包
- 下一篇: bzoj2746: [HEOI2012]