BZOJ 3714: [PA2014] Kuglarz (Minimum Spanning Tree), bzoj3714
Time Limit: 20 Sec Memory Limit: 128 MB
Submit: 1134 Solved: 599
[Submit] [Status] [Discuss] Description
The magician's table contains n cups in a row numbered 1, 2 ,..., N. Some of the cups have a small ball under them. If you accurately guess which cups are under them, you will be given a prize. The magician will tell you the cup I, I + 1 ,..., The parity of the total number of balls hidden under j.
To adopt the optimal inquiry strategy, you need to spend at least how much to make sure you can guess which cups have the ball hidden under them?
Input
The first line is an integer n (1 <=n <= 2000 ).
Line I + 1 (1 <= I <= n) has n + 1-i integers, indicating the cost of each query. C_ij (the cost for querying the range [I, j], 1 <= I <= j <= n, 1 <= c_ij <= 10 ^ 9) the number of j + 1-i in line I + 1.
Output
Returns an integer that indicates the minimum cost.
Sample Input5
1 2 3 4 5
4 3 2 1
3 4 5
2 1
5
Sample Output7HINT Source
Thanks to Jcvb
QWQ ..
Let's change the model of this question.
$ Sum [I] $ indicates the prefix and
In this case, we assume that the parity of $ I-j $ is actually the parity of $ sum [j]-sum [I-1] $.
Therefore, if we want to require the parity of $ sum [j]-sum [I-1] $, We will connect an edge between $ I-1 $ and $ j $ for the requested weight
Eventually, the entire graph is required to be connected.
Therefore, we can run the smallest Spanning Tree on one side.
Of course, if you are as weak as me, it is not difficult to find out after observation.
When we know $1-2 $, we only need to know $1-1 $ or $2-2 $,
If you need to know $1-3 $, you only need to know $3-3 $.
If we continue to push it down, we will find that the optimal query range does not overlap with each other by giving more examples.
This is the minimal spanning tree!
Then the code is written to GG ....
#include<cstdio>#include<algorithm>#define int long long const int MAXN=3*1e6+10;using namespace std;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;struct node{ int u,v,w;}edge[MAXN];int num=1;void AddEdge(int x,int y,int z){ edge[num].u=x; edge[num].v=y; edge[num++].w=z;}int comp(const node &a,const node &b){return a.w<b.w;}int fa[MAXN];int find(int x){ if(fa[x]==x) return fa[x]; else return fa[x]=find(fa[x]);}void unionn(int x,int y){ int fx=find(x); int fy=find(y); fa[fx]=fy;}void Kruskal(){ sort(edge+1,edge+num,comp); int tot=0,sum=0; for(int i=1;i<=num-1;i++) { if(find(edge[i].u)!=find(edge[i].v)) { unionn(edge[i].u,edge[i].v); sum+=edge[i].w; tot++; if(tot==N) break; } } printf("%lld",sum);}main(){ #ifdef WIN32 freopen("a.in","r",stdin); #else #endif N=read(); for(int i=1;i<=N;i++) fa[i]=i; for(int i=1;i<=N;i++) { for(int j=i;j<=N;j++) { int x=read(); AddEdge(i-1,j,x); } } Kruskal(); return 0;}