「BZOJ3714」[PA2014] Kuglarz
Description
魔术师的桌子上有n个杯子排成一行,编号为1,2,…,n,其中某些杯子底下藏有一个小球,如果你准确地猜出是哪些杯子,你就可以获得奖品。花费c_ij元,魔术师就会告诉你杯子i,i+1,…,j底下藏有球的总数的奇偶性。
采取最优的询问策略,你至少需要花费多少元,才能保证猜出哪些杯子底下藏着球?
Input
第一行一个整数n(1<=n<=2000)。
第i+1行(1<=i<=n)有n+1-i个整数,表示每一种询问所需的花费。其中c_ij(对区间[i,j]进行询问的费用,1<=i<=j<=n,1<=c_ij<=10^9)为第i+1行第j+1-i个数。
Output
输出一个整数,表示最少花费。
Sample Input
5
1 2 3 4 5
4 3 2 1
3 4 5
2 1
5
1 2 3 4 5
4 3 2 1
3 4 5
2 1
5
Sample Output
7
题解
最小生成树。。。不要问我为什么 (跪在电脑前)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 |
#include<iostream> #include<cstdio> #include<cstring> #include<cstdlib> #include<algorithm> #include<cmath> #include<queue> #include<set> #include<map> #include<ext/pb_ds/priority_queue.hpp> #define pa pair<int,int> #define inf 1000000000 #define ll long long using namespace std; using namespace __gnu_pbds; inline int read() { int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } int n; ll ans; int a[2005][2005],dis[2005]; bool vis[2005]; __gnu_pbds::priority_queue<pa,greater<pa> >::point_iterator id[2005]; void prim() { __gnu_pbds::priority_queue<pa,greater<pa> >q; for(int i=1;i<=n;i++)dis[i]=inf; dis[0]=0; id[0]=q.push(make_pair(0,0)); while(!q.empty()) { int now=q.top().second;q.pop(); ans+=dis[now];vis[now]=1; for(int i=1;i<=n;i++) if(a[now][i]<dis[i]&&!vis[i]) { dis[i]=a[now][i]; if(id[i]==0)id[i]=q.push(make_pair(dis[i],i)); else q.modify(id[i],make_pair(dis[i],i)); } } } int main() { n=read(); for(int i=1;i<=n;i++) for(int j=i;j<=n;j++) a[i-1][j]=a[j][i-1]=read(); prim(); printf("%lld",ans); return 0; } |
差分约束啊就是
Orzzzzzzz求解释
去把bzoj1202做了吧,就知道为什么了
我去做了…然后..觉得相似地方好像就用到前缀和的性质,然后蒟蒻求教此题怎么差分约束
那题不是要用到并查集吗QAQ,这个题也是弄一个前缀和(异或和),然后就会有n(n+1)/2个等式,全是等式就代表这个图中任意一对点之间的所有路径长度是相同的。每次魔术师可以知道任意两个点之间的路径长度,所以就是最小生成树了,这东西就是差分约束的一种情况啊,每个等式a = b可以看做联立 a >= b和 a <= b