CF1512D Corrupted Array 题解
Posted yuhang-ren
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CF1512D Corrupted Array 题解相关的知识,希望对你有一定的参考价值。
CF1512D Corrupted Array 题解
Link
Description
给定一个正整数 \\(n\\) 和长度为 \\(n+2\\) 的数组 \\(b\\),数组 \\(b\\) 是依据如下算法构造的:
- 随机生成一个含有 \\(n\\) 个元素的原始数组\\(a\\);
- 把数组 \\(a\\) 赋值给数组 \\(b\\),即 \\(b_i=a_i(1\\le i\\le n)\\);
- 数组 \\(b\\) 的第 \\(n+1\\) 个元素为数组 \\(a\\) 的元素和,即 \\(b_n+1=\\sum_i=1^na_i\\);
- 数组 \\(b\\) 的第 \\(n+2\\) 个元素是个随机整数 \\(x(1\\le x\\le10^9)\\);
- 打乱 \\(b\\) 数组。
例如,数组 \\(b=[2,3,7,12,2]\\),那么它能够通过如下方式构建:
- \\(a=[2,2,3]\\),且 \\(x=12\\);
- \\(a=[3,2,7]\\),且 \\(x=2\\)。
给定一个 \\(b\\) 数组,请你求出它对应的 \\(a\\) 数组。
Solution
假设打乱前的 \\(b\\) 数组为 \\(c\\),记所有数的和为 \\(sum\\)。
将 \\(b\\) 数组排序,为了满足数组 \\(c\\) 的第 \\(n+1\\) 个元素为数组 \\(a\\) 的元素和,和一定为最大的数或第二大的数(此时对应的随机数为最大的数)。
在排序后的 \\(b\\) 数组中枚举随机数,设当前位置为 \\(i\\)。
-
当 \\(i = n + 2\\) 时,\\(sum - b_n + 2 - b_n + 1 = b_n + 1\\) 时满足条件,此时输出 \\(b_1,\\ldots,b_n\\) 即可。
-
否则当 \\(sum - b_n + 2 - b_i = b_n + 2\\) 时满足条件,此时对于所有的 \\((1 \\leq k \\leq n + 1)\\) 且 \\(k \\ne i\\) 输出 \\(b_k\\) 即可。
全部枚举仍无答案则无解。
Codes
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define max_n 300010
void read(int &p)
p = 0;
int k = 1;
char c = getchar();
while (c < \'0\' || c > \'9\')
if (c == \'-\')
k = -1;
c = getchar();
while (c >= \'0\' && c <= \'9\')
p = p * 10 + c - \'0\';
c = getchar();
p *= k;
return;
void write_(int x)
if (x < 0)
putchar(\'-\');
x = -x;
if (x > 9)
write_(x / 10);
putchar(x % 10 + \'0\');
void writesp(int x)
write_(x);
putchar(\' \');
void writeln(int x)
write_(x);
putchar(\'\\n\');
int T, n, nums[max_n];
signed main()
#if _clang_
freopen("1.in", "r", stdin);
freopen("1.out", "w", stdout);
#endif
read(T);
while (T--)
read(n);
int sum = 0;
for (int i = 1; i <= n + 2; i++)
read(nums[i]);
sum += nums[i];
sort(nums + 1, nums + n + 3);
if (sum - nums[n + 2] - nums[n + 1] == nums[n + 1] || sum - nums[n + 2] - nums[n + 1] == nums[n + 2])
for (int i = 1; i <= n; i++)
writesp(nums[i]);
puts("");
continue;
int ans = -1;
for (int i = 1; i <= n; i++)
if (sum - nums[n + 2] - nums[i] == nums[n + 2])
ans = i;
continue;
if (ans == -1)
puts("-1");
continue;
else
for (int i = 1; i <= n + 1; i++)
if (i == ans)
continue;
writesp(nums[i]);
puts("");
return 0;
本文来自博客园,作者:yuhang-ren,转载请注明原文链接:https://www.cnblogs.com/yuhang-ren/p/17415081.html
IndiaHacks 2016 - Online Edition (CF) . D
这题思路很简单,二分m,求最大流是否大于等于x。
但是比赛过程中大部分的代码都被hack了。。。
精度问题,和流量可能超int
关于精度问题,这题真是提醒的到位,如果是先用二分将精度控制在10^-8左右,最后乘一个10^4,精度只能在10-4,而二分控制精度在10^-11很容易死循环(因为double 保存15-16位有效数字,结果可能为10^6级,精确到10-11,double做不到)
所以这题二分可以不写成while(d-b>eps),而直接规定二分的次数,设置成100次,基本可以保证14-15位有效数字都正确了,这时再乘10^4还是能够达到题目中要求的10^-6的精度。
还有一种处理精度的方法:
直接定义上下界就为输出的最后结果,在判断的过程中除以x,最后输出也能满足要求。
第一种精度处理方式:
#include <stdio.h> #include <string.h> #include <algorithm> #include <vector> #include <math.h> #include <iostream> using namespace std; #define eps 1e-11 #define N 55 #define M 500500 #define INF 0x3fffff struct node1 { long long to,w,next; }edge[M]; long long sn,sm,sx; long long pre[10*N]; long long g[N][N]; long long gap[10*N],lv[10*N]; long long k,c,m; long long cnt; long long n,nn; long long s,t; long long ans; long long sum; void add_edge(long long u,long long v,long long w) { edge[cnt].to=v; edge[cnt].w=w; edge[cnt].next=pre[u]; pre[u]=cnt++; } long long gdfs(long long k,long long w) { if(k==t) return w; long long f=0; long long mi=nn-1; for(long long p=pre[k];p!=-1;p=edge[p].next) { long long v=edge[p].to,tw=edge[p].w; if(tw!=0) { if(lv[k]==lv[v]+1) { long long tmp=gdfs(v,min(tw,w-f)); f+=tmp; edge[p].w-=tmp; edge[p^1].w+=tmp; if(f==w||lv[s]==nn) break; } if(lv[v]<mi) mi=lv[v]; } } if(f==0) { gap[lv[k]]--; if( gap[ lv[k] ]==0 ) { lv[s]=nn; } lv[k]=mi+1; gap[lv[k]]++; } return f; } long long sap() { memset(lv,0,sizeof(lv)); memset(gap,0,sizeof(gap)); gap[0]=nn; while(lv[s]<nn) { sum+=gdfs(s,INF); } return sum; } long long a[505],b[505],kk[505]; long long check(double mid) { sum=0; //mid/=sx; memset(pre,-1,sizeof(pre)); cnt=0; for(long long i=0;i<sm;i++) { add_edge(a[i],b[i],(long long)(kk[i]/mid+eps)); add_edge(b[i],a[i],0); } if(sap()>=sx) { return 1; } else return 0; } int main() { cin>>sn>>sm>>sx; for(long long i=0;i<sm;i++) { cin>>a[i]>>b[i]>>kk[i]; } s=1; t=sn; nn=t+1; //这个精度问题还是很坑。。。 double b=0,d=10000000.0; //好坑的东西! 我就操! int time=160; while(time--)//这里精度太小,竟然会死循环。。。 { double mid=(b+d)/2; if( check(mid)==1 ) { b = mid; } else { d = mid; } } printf("%.10lf",b*sx); return 0; }
第二种精度处理方式:
#include <stdio.h> #include <string.h> #include <algorithm> #include <vector> #include <math.h> #include <iostream> using namespace std; #define eps 1e-11 #define N 55 #define M 500500 #define INF 0x3fffff struct node1 { long long to,w,next; }edge[M]; long long sn,sm,sx; long long pre[10*N]; long long g[N][N]; long long gap[10*N],lv[10*N]; long long k,c,m; long long cnt; long long n,nn; long long s,t; long long ans; long long sum; void add_edge(long long u,long long v,long long w) { edge[cnt].to=v; edge[cnt].w=w; edge[cnt].next=pre[u]; pre[u]=cnt++; } long long gdfs(long long k,long long w) { if(k==t) return w; long long f=0; long long mi=nn-1; for(long long p=pre[k];p!=-1;p=edge[p].next) { long long v=edge[p].to,tw=edge[p].w; if(tw!=0) { if(lv[k]==lv[v]+1) { long long tmp=gdfs(v,min(tw,w-f)); f+=tmp; edge[p].w-=tmp; edge[p^1].w+=tmp; if(f==w||lv[s]==nn) break; } if(lv[v]<mi) mi=lv[v]; } } if(f==0) { gap[lv[k]]--; if( gap[ lv[k] ]==0 ) { lv[s]=nn; } lv[k]=mi+1; gap[lv[k]]++; } return f; } long long sap() { memset(lv,0,sizeof(lv)); memset(gap,0,sizeof(gap)); gap[0]=nn; while(lv[s]<nn) { sum+=gdfs(s,INF); } return sum; } long long a[505],b[505],kk[505]; long long check(long double mid) { sum=0; mid/=sx; memset(pre,-1,sizeof(pre)); cnt=0; for(long long i=0;i<sm;i++) { add_edge(a[i],b[i],(long long)(kk[i]/mid+eps)); add_edge(b[i],a[i],0); } if(sap()>=sx) { return 1; } else return 0; } int main() { cin>>sn>>sm>>sx; for(long long i=0;i<sm;i++) { cin>>a[i]>>b[i]>>kk[i]; } s=1; t=sn; nn=t+1; //这个精度问题还是很坑。。。 long double b=0,d=1000000000.0; //好坑的东西! 我就操! while(d-b > 1e-13)//这里精度太小,竟然会死循环。。。 { long double mid=(b+d)/2; if( check(mid)==1 ) { b = mid; } else { d = mid; } } printf("%.20Lf",b); return 0; }
以上是关于CF1512D Corrupted Array 题解的主要内容,如果未能解决你的问题,请参考以下文章