CF1140G Double Tree题解

CF1140G Double Tree题解

我实在太弱了,想不出看题解竟然看不懂\(O(n)\)做法,不过好歹得到了一点启发,自己写下了\(O(nlog_{n})\)的倍增的极其丑陋的代码:
预处理大部分思路跟楼上巨佬相同,
将图视作两棵树,一棵全是奇点,编号为0,一棵全是偶点,编号为1,两部分的对应点之间一一有边相连。
先求出两棵树对应点之间的最小距离,
用两遍\(dfs\),一遍\(dfs\)求出走子树的对应点之间的最小距离,另一遍\(dfs3\)在此基础上看看是否能通过走父辈节点来更新最小距离。
CF1140G Double Tree题解_第1张图片

接下来dfs2遍历预处理出倍增数组:
\(g[x][y][z]\)代表\(y\)\(y*2^{n}\)的状态为\(x\)\(y\)为当前点,\(z\)是倍增数。
其中
\(\left\{\begin{matrix} x=0:y\in {tree_{0}},z\in {tree_{0}} & \\x=1:y\in {tree_{1}},z\in {tree_{0}} & \\x=2:y\in {tree_{0}},z\in {tree_{1}} & \\x=3:y\in {tree_{1}},z\in {tree_{1}} & \end{matrix}\right.\)
由此我们可以推断出核心代码:
\(\left\{\begin{matrix} g[0][x][i]=min(g[0][x][i-1]+g[0][f[x][i-1]][i-1],g[2][x][i-1]+g[1][f[x][i-1]][i-1]); \\g[1][x][i]=min(g[1][x][i-1]+g[0][f[x][i-1]][i-1],g[3][x][i-1]+g[1][f[x][i-1]][i-1]); \\g[2][x][i]=min(g[0][x][i-1]+g[2][f[x][i-1]][i-1],g[2][x][i-1]+g[3][f[x][i-1]][i-1]); \\g[3][x][i]=min(g[1][x][i-1]+g[2][f[x][i-1]][i-1],g[3][x][i-1]+g[3][f[x][i-1]][i-1]); \end{matrix}\right.\)
举个栗子:
CF1140G Double Tree题解_第2张图片

\(g[0][x][i]\)便可能由\(g[0][x][i-1],g[0][f[x][i-1][i-1]]\)\(g[2][x][i-1],g[1][f[x][i-1]][i-1]\)转移过来
至于后面\(lca\)操作\(ans[][][]\)的转移,
只是样子看起来和这个有点不一样,本质是相同的。
记得注意一下\(ans[][][]\)的初值,想想为什么这么赋。
还有返回值,记得\(lca\)的状态要一致,故只有两种状态。

#include
#define ll long long
using namespace std;
const int N=3e5+6;
const ll inf=2e17;
int n,q,t1,t2,cnt=0,head[N],f[N][21],d[N];
ll t3,t4,w[N],g[4][N][21];
struct edge{int nxt,to; ll w,p;}e[N<<1];
inline void add(int u,int v,ll w,ll p){e[++cnt].nxt=head[u],e[cnt].to=v,e[cnt].w=w,e[cnt].p=p,head[u]=cnt;}
inline ll read(){
   ll F=1,T=0; char ch=getchar(); 
   while(ch<'0'||ch>'9'){if(ch=='-') F=-1; ch=getchar();}
   while(ch>='0'&&ch<='9') T=(T<<3)+(T<<1)+(ch-48),ch=getchar();
   return F*T;
}
void dfs(int x,int fa){for(int i=head[x];i;i=e[i].nxt) if(e[i].to!=fa) dfs(e[i].to,x),w[x]=min(w[x],w[e[i].to]+e[i].w+e[i].p);}
void dfs3(int x,int fa){for(int i=head[x];i;i=e[i].nxt) if(e[i].to!=fa) w[e[i].to]=min(w[e[i].to],w[x]+e[i].w+e[i].p),dfs3(e[i].to,x);}
void dfs2(int x,int fa){
     f[x][0]=fa,d[x]=d[fa]+1;
     for(int i=1;i<=20;++i){
         f[x][i]=f[f[x][i-1]][i-1];
         g[0][x][i]=min(g[0][x][i-1]+g[0][f[x][i-1]][i-1],g[2][x][i-1]+g[1][f[x][i-1]][i-1]),g[1][x][i]=min(g[1][x][i-1]+g[0][f[x][i-1]][i-1],g[3][x][i-1]+g[1][f[x][i-1]][i-1]);
         g[2][x][i]=min(g[0][x][i-1]+g[2][f[x][i-1]][i-1],g[2][x][i-1]+g[3][f[x][i-1]][i-1]),g[3][x][i]=min(g[1][x][i-1]+g[2][f[x][i-1]][i-1],g[3][x][i-1]+g[3][f[x][i-1]][i-1]);
     }
     for(int i=head[x];i;i=e[i].nxt)
         if(e[i].to!=fa){
            g[0][e[i].to][0]=min(e[i].w,w[e[i].to]+e[i].p+w[x]),g[3][e[i].to][0]=min(e[i].p,w[e[i].to]+e[i].w+w[x]);
            g[1][e[i].to][0]=min(e[i].p+w[x],e[i].w+w[e[i].to]),g[2][e[i].to][0]=min(e[i].p+w[e[i].to],e[i].w+w[x]),dfs2(e[i].to,x); 
         }
}
ll lca(int u,int v,int x,int y){
   int pp=0,qq=0;
   if(u==v) return w[u];
   if(d[u]=0;--i)
       if(d[u]>=d[v]+(1<=0;--i)
       if(f[u][i]!=f[v][i]){
          pp^=1,qq^=1;
          ans[qq][1][0]=min(ans[qq^1][1][0]+g[0][v][i],ans[qq^1][1][2]+g[1][v][i]),ans[qq][1][1]=min(ans[qq^1][1][1]+g[0][v][i],ans[qq^1][1][3]+g[1][v][i]);
          ans[qq][1][2]=min(ans[qq^1][1][0]+g[2][v][i],ans[qq^1][1][2]+g[3][v][i]),ans[qq][1][3]=min(ans[qq^1][1][1]+g[2][v][i],ans[qq^1][1][3]+g[3][v][i]),v=f[v][i];
          ans[pp][0][0]=min(ans[pp^1][0][0]+g[0][u][i],ans[pp^1][0][2]+g[1][u][i]),ans[pp][0][1]=min(ans[pp^1][0][1]+g[0][u][i],ans[pp^1][0][3]+g[1][u][i]);
          ans[pp][0][2]=min(ans[pp^1][0][0]+g[2][u][i],ans[pp^1][0][2]+g[3][u][i]),ans[pp][0][3]=min(ans[pp^1][0][1]+g[2][u][i],ans[pp^1][0][3]+g[3][u][i]),u=f[u][i];
       }
   pp^=1,qq^=1;
   ans[qq][1][0]=min(ans[qq^1][1][0]+g[0][v][0],ans[qq^1][1][2]+g[1][v][0]),ans[qq][1][1]=min(ans[qq^1][1][1]+g[0][v][0],ans[qq^1][1][3]+g[1][v][0]);
   ans[qq][1][2]=min(ans[qq^1][1][0]+g[2][v][0],ans[qq^1][1][2]+g[3][v][0]),ans[qq][1][3]=min(ans[qq^1][1][1]+g[2][v][0],ans[qq^1][1][3]+g[3][v][0]),v=f[v][0];
   ans[pp][0][0]=min(ans[pp^1][0][0]+g[0][u][0],ans[pp^1][0][2]+g[1][u][0]),ans[pp][0][1]=min(ans[pp^1][0][1]+g[0][u][0],ans[pp^1][0][3]+g[1][u][0]);
   ans[pp][0][2]=min(ans[pp^1][0][0]+g[2][u][0],ans[pp^1][0][2]+g[3][u][0]),ans[pp][0][3]=min(ans[pp^1][0][1]+g[2][u][0],ans[pp^1][0][3]+g[3][u][0]),u=f[u][0];
   return min(ans[pp][0][x]+ans[qq][1][y],ans[pp][0][x+2]+ans[qq][1][y+2]);
}
int main(){
    n=read();
    for(int i=1;i<=n;++i) w[i]=read();
    for(int i=1;i>1,(t2+1)>>1,!(t1&1),!(t2&1)));
    return 0;
} 

你可能感兴趣的:(CF1140G Double Tree题解)