[bzoj3714] [PA2014]Kuglarz
这竟然是最小生成树。。哭瞎。
记前缀和的奇偶性为pre[],要确定一个点的奇偶性,肯定要知道pre[i]和pre[i-1],或者pre[i+1]和pre[i](不一定是直接询问得出的,总之肯定要知道pre[i]
如果将查询区间[l,r]总和的奇偶性视为一条边(l-1,r)(因为是pre[r]-pre[l-1]),
要知道所有的pre值,也就是通过连边,使所有的点与0相连通。
然后就变成mst了。。。
1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 #include<algorithm> 5 #define ll long long 6 using namespace std; 7 const int maxn=2023; 8 int dis[maxn],c[maxn][maxn]; 9 bool u[maxn]; 10 ll ans; 11 int i,j,k,n,m; 12 13 int ra;char rx; 14 inline int read(){ 15 rx=getchar(),ra=0; 16 while(rx<'0'||rx>'9')rx=getchar(); 17 while(rx>='0'&&rx<='9')ra*=10,ra+=rx-48,rx=getchar();return ra; 18 } 19 inline void prim(){ 20 int mx;register int i; 21 dis[0]=1e9; 22 for(i=1;i<=n;i++)dis[i]=c[0][i]; 23 for(int j=1;j<=n;j++){ 24 mx=0;for(i=1;i<=n;i++)if(!u[i]&&dis[i]<dis[mx])mx=i; 25 // printf("mx:%d dis:%d\n",mx,dis[mx]); 26 ans+=dis[mx],u[mx]=1; 27 for(i=1;i<=n;i++)if(!u[i]&&c[mx][i]<dis[i])dis[i]=c[mx][i]; 28 } 29 } 30 int main(){ 31 n=read(); 32 for(i=1;i<=n;i++)for(j=i;j<=n;j++)c[i-1][j]=c[j][i-1]=read(); 33 prim(); 34 printf("%lld\n",ans); 35 } 36