含n(
≤10w)
個結點的樹。邊權為
1 ,點權ai
∈[1,
10w]。求點權互質的點之間的距離之和。
#include
#include
#include
#include
#define rep(x,st,en) for(int x=st;x<=en;x++)
#pragma comment(linker, "/stack:1024000000,1024000000")
using
namespace
std;
const
int m=100005;
const
int num=100000;
typedef
long
long ll;
int nxt[m][18],bin[20];
int dep[m];
struct edgeedge[m<<2];
//虛樹中的邊可以利用深度o(1)獲得
int last[m];
int head[m];
int prv,allc;
int mul[m];
int id[m],n;
ll ans,val;
void ins(int u,int v);
last[u]=allc;
}void ins_(int u,int v);
head[u]=allc;
}bool cmp(int x,int y)
return nxt[u][0];
}int stk[m];
int sz[m];
void dfs1(int x,int f)
}if(f)val+=1ll*abs(dep[x]-dep[f])*sz[x]*(tot-sz[x]);
}void clear(int x,int f)
last[x]=sz[x]=0;
}void solve(int k)
else
if(dep[f]break;
}else
break;
}if(stk[top]!=f)stk[++top]=f;
stk[++top]=s;
}while(top>1)
dfs1(a[0],0);
ans+=val*mul[k];
clear(a[0],0);
// printf("%i64d\n",val);
}void dfs(int x,int f)
}char mark[m];
int prm[m];
void pre()
for(int j=0;jtrue;
if(i%prm[j]==0)
else mul[i*prm[j]]=-mul[i];}}
}int main()
prv=allc;
for(int u,v,i=1;iscanf("%d%d",&u,&v);
ins(u,v);ins(v,u);
}//這裡的邊得到dfs序和深度以後就用不到了
dfs_clock=0;
dfs(1,0);
ans=0;
for(int i=1;i<=n;i++)
last[i]=0;
for(int i=1;i<=num;i++)
if(mul[i])solve(i);
cout
0;}
計蒜客習題 蒜頭君的建設方案
說是樹狀dp的入門水題,然而甚至感覺不到dp的存在。好吧,理論上這個確實是dp,由之前階段推出當前階段,以子結點為根的子樹結點個數可以推出以父結點為根的子樹結點個數。然後針對每條邊,根據題目要求的那樣統計答案即可。不過我們統計時利用的應該是子結點的資訊,怎麼找到子結點?因為父結點的資訊是由子結點的資...
計蒜客 微軟大樓設計方案(RMQ)
題目鏈結 微軟大樓設計方案 中文題就不說題意了 首先是簡單版本 滿足 1 n,m 50 那麼設 c i j 為從第 i 幢樓到第 j 幢樓的最低的那幢樓的高度 計算兩個點之間的距離的時候,若兩個點分別在第 i 列,第 j 列,那麼要根據 c i j 來計算。暴力即可 include using na...
計蒜客 單獨的數字
給定乙個陣列 a,除了乙個數出現一次之外,其餘數都出現三次。找出出現一次的數。如 找出 7。你的演算法只能是線性時間的複雜度,並且不能使用額外的空間哦 輸入格式 第一行輸入乙個數n 1 n 500 代表陣列的長度。接下來一行輸入 n 個 int 範圍內 2147483648 2147483647 的...