Solution
很巧妙的一道题……
如果想知道位置 (i) 是否有球,那就必须知道 ([i,i+1)) 的奇偶性。反映在图上,就是点 (i) 和 (i+1) 必须是连通的,那么如果需要知道所有位置是否有球,那么 (1) 到 (n+1) 的所有点都必须连通。用边 (u o v) 来表示询问区间 ([u,v)),花费 (c_{u,v-1})。跑最小生成树就求出了答案。
考虑这样做的正确性。如果 (u) 和 (v) 在图中是连通的,说明 (u) 和 (v) 之间有一条通路。这条通路上的每条边都表示一个询问 ([u_i,v_i))。容易知道,将这些询问的答案异或起来,其实就是区间 ([u,v)) 的奇偶性。也就是说如果 (u) 和 (v) 连通,那它们之间的奇偶性就能知道了。那么最小生成树就是使得图连通的最小花费。
#include<stdio.h>
#include<algorithm>
using namespace std;
#define N 2007
inline int read(){
int x=0,flag=1; char c=getchar();
while(c<'0'||c>'9'){if(c=='-') flag=0;c=getchar();}
while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+c-48;c=getchar();}
return flag? x:-x;
}
struct E{
int u,v,dis;
bool operator<(const E &X)const{return dis<X.dis;}
}e[N*N];
int n,tot=0,fa[N],cnt;
inline int find(int x){
if(fa[x]==x) return x;
return fa[x]=find(fa[x]);
}
int main(){
n=cnt=read();
for(int i=1;i<=n;i++)
for(int j=i;j<=n;j++)
e[++tot]=(E){i,j+1,read()};
for(int i=1;i<=n+1;i++) fa[i]=i;
sort(e+1,e+1+tot);
long long ans=0;
for(int i=1;i<=tot;i++){
int u=e[i].u,v=e[i].v;
int fa_u=find(u),fa_v=find(v);
if(fa_u==fa_v) continue;
fa[fa_v]=fa_u;
ans+=1ll*e[i].dis;
if(!(--cnt)) break;
}
printf("%lld",ans);
}