Codeforces Round #351 (VK Cup 2016 Round 3, Div. 2 Edition)
2016-05-08 21:39
639 查看
链接:http://codeforces.com/contest/673
problemA. Bear and Game:看90分钟电视,有n个有趣点,如果持续15没有看到有趣的点,那么就关电视,问什么时候会关掉电视。
分析:水题。找到第一个跨度大于15的点即可,注意答案最大90。
代码:
#include<map> #include<set> #include<cmath> #include<queue> #include<bitset> #include<math.h> #include<cstdio> #include<vector> #include<string> #include<cstring> #include<iostream> #include<algorithm> #pragma comment(linker, "/STACK:102400000,102400000") using namespace std; const int N=500010; const int MAX=1000000100; const int mod=100000000; const int MOD1=1000000007; const int MOD2=1000000009; const double EPS=0.00000001; typedef long long ll; const ll MOD=998244353; const int INF=1000000010; typedef double db; typedef unsigned long long ull; int a[100]; int main() { int i,n,ans=0; scanf("%d", &n); for (i=1;i<=n;i++) scanf("%d", &a[i]); sort(a+1,a+n+1);a[0]=0; for (i=1;i<=n;i++) if (a[i]-a[i-1]>15) break ; else ans=a[i]; printf("%d\n", min(ans+15,90)); return 0; }
problemB. Problems for Round:给定n个人,编号1~n,将这n个人分为两组,给定m个关系,每组关系a,b表示a和b不能在同一组,并且所有关系中较小的在一组,较大的在一组。在较小组中的数要小于任何一个在较大组的数,问有多少种分法。
分析:较小组中存下最大值,较大组中存下最小值,看中间有多少个数是自由的即可,注意关系m==0的情况。
代码:
#include<map> #include<set> #include<cmath> #include<queue> #include<bitset> #include<math.h> #include<cstdio> #include<vector> #include<string> #include<cstring> #include<iostream> #include<algorithm> #pragma comment(linker, "/STACK:102400000,102400000") using namespace std; const int N=500010; const int MAX=1000000100; const int mod=100000000; const int MOD1=1000000007; const int MOD2=1000000009; const double EPS=0.00000001; typedef long long ll; const ll MOD=998244353; const int INF=1000000010; typedef double db; typedef unsigned long long ull; int main() { int i,n,m,mi,mx,x,y; scanf("%d%d", &n, &m); mi=0;mx=n+1; for (i=1;i<=m;i++) { scanf("%d%d", &x, &y); if (x>y) swap(x,y); mi=max(mi,x);mx=min(mx,y); } if (mi==0) { printf("%d\n", n-1);return 0; } if (mx<mi) printf("0\n"); else printf("%d\n", mx-mi); return 0; }
problemC. Bear and Colors:给定n个数,每个数都在1~n以内,会形成n*(n+1)/2个区间,设x为区间的众数(多个众数取最小的那一个),然后ans[x]++。求统计完所有区间后的ans数组。
分析:固定区间左端点L,然后扩展右端点R,没扩展一次得到一个众数x就ans[x]++即可。
代码:
#include<map> #include<set> #include<cmath> #include<queue> #include<bitset> #include<math.h> #include<cstdio> #include<vector> #include<string> #include<cstring> #include<iostream> #include<algorithm> #pragma comment(linker, "/STACK:102400000,102400000") using namespace std; const int N=5010; const int MAX=1000000100; const int mod=100000000; const int MOD1=1000000007; const int MOD2=1000000009; const double EPS=0.00000001; typedef long long ll; const ll MOD=998244353; const int INF=1000000010; typedef double db; typedef unsigned long long ull; int a ,ans ,num ; int main() { int i,j,n,g,co; scanf("%d", &n); for (i=1;i<=n;i++) scanf("%d", &a[i]); for (i=1;i<=n;i++) { g=0;co=0; for (j=i;j<=n;j++) { num[a[j]]++; if (num[a[j]]>g) { g=num[a[j]];co=a[j]; } if (num[a[j]]==g&&a[j]<co) { g=num[a[j]];co=a[j]; } ans[co]++; } for (j=i;j<=n;j++) num[a[j]]--; } for (i=1;i<=n;i++) printf("%d ", ans[i]); printf("\n"); return 0; }
problemD. Bear and Two Paths:给定点数n和k,a,b,c,d。表示要构造出两条长度为n的链v1-v2-...-vn,u1-u2-...-un。v和u都是n的一个排列,表示路径中点的顺序。其中v1==a&&vn==b和u1==c&&un==d且a-b不能直接用边相连,c-d不能直接用边相连。要求最多只能构造k条边(双向边)。无解输出-1,有解输出v和u。
分析:因为要在k条边以内构造出来,我们能想到应该有最优的构造方法。我们再想想无解的情况首先考虑点的约束:很容易想到n==4是无解的,n>4时都能用一个辅助点达到要求然后只要看边的约束。边的约束:首先我们能想到这两条路径要构出至少2个环且最好将能重复使用的边重复使用。知道这些之后画画图就能想出这个模型:构造一个不属于(a,b,c,d)的点e作为辅助点,构造6条边:a-e,a-c,c-e,b-d,b-e,d-e。然后对于多出的点我们只要将它们连成链然后插入到这6条边中任意一个位置即可。这显然是最优的n>4&&边为n+1。
代码:
#include<map> #include<set> #include<cmath> #include<queue> #include<bitset> #include<math.h> #include<cstdio> #include<vector> #include<string> #include<cstring> #include<iostream> #include<algorithm> #pragma comment(linker, "/STACK:102400000,102400000") using namespace std; const int N=500010; const int MAX=1000000100; const int mod=100000000; const int MOD1=1000000007; const int MOD2=1000000009; const double EPS=0.00000001; typedef long long ll; const ll MOD=998244353; const int INF=1000000010; typedef double db; typedef unsigned long long ull; int p[1010]; int main() { int a,b,c,d,e,i,n,k; scanf("%d%d", &n, &k); scanf("%d%d%d%d", &a, &b, &c, &d); memset(p,0,sizeof(p)); p[a]=p[b]=p[c]=p[d]=1; for (i=1;i<=n;i++) if (!p[i]) { e=i;p[i]=1;break ; } if (n<5||k<n+1) printf("-1\n"); else { printf("%d ", a); for (i=1;i<=n;i++) if (!p[i]) printf("%d ", i); printf("%d %d %d %d\n", c, e, d, b); printf("%d ", c); for (i=n;i;i--) if (!p[i]) printf("%d ", i); printf("%d %d %d %d\n", a, e, b, d); } return 0; }
problemE. Levels and Regions:给定n个数t[1]~t
,给定组数k,将这n个数分为k组,然后求一个期望。规则:1:同一组的元素是连续的,且组不能为空。2:每次找到第一个组(有元素未被杀死),设最小的未死元素为X,不存在则结束游戏。3:对于选定的组G和元素X,将G中杀死的元素i放t[i]个小球到抽奖箱,放t[X]个小球到抽奖箱,然后等概率的抽一个小球,这个操作花费1小时,抽到的小球代表的元素被杀死(如果是已经被杀死就跳过)。要你进行分组,使得所有元素都被杀死需要花费的时间的期望最小。
分析:首先因为同一组只能是连续的元素,我们就要会算连续的[l,r]成为一组是全部被杀死的期望时间,最基础的期望问题,设期望为F[l,r],那么会有F[l,r]=sigma(sum[i]/t[i]-sum[l-1]/t[i]),{l<=i<=r},那么我们就能设dp[i][j]表示将前j个元素分为i个组花费的最小期望。那么状态转移方程式为:dp[i][j]=min(dp[i][k]+F[k,j]),我们设Si=sigma(1<=j<=i)t[j],Qi=sigma(1<=j<=i)Sj/tj,Ri=sigma(1<=j<=i)1/tj。然后我们将dp[i][j]中的F[k,j]用这些表达式替换能得到:dp[i][j]=min(dp[i][k]-Qk+Sk*Rk-Sk*Rj+Qj),这里很明显的斜率优化了。维护一个下凸包就能在O(1)的时间中转移状态啦。O(n*k)。
代码:
#include<map> #include<set> #include<cmath> #include<queue> #include<bitset> #include<math.h> #include<cstdio> #include<vector> #include<string> #include<cstring> #include<iostream> #include<algorithm> #pragma comment(linker, "/STACK:102400000,102400000") using namespace std; const int N=1000010; const int MAX=151; const int mod=100000000; const int MOD1=100000007; const int MOD2=100000009; const double EPS=0.00000001; typedef long long ll; const ll MOD=1000000000; const ll INF=1000000000010; typedef double db; typedef long double ldb; typedef unsigned long long ull; ll hea,top,t ; ldb dx ,dy ,dp[2] ,sum ,sump ,sumq ; int cala(ldb x,ldb y,ldb x1,ldb y1,ldb x2,ldb y2) { return (y2-y1)*(x1-x)>=(y1-y)*(x2-x1); } void add(ldb x,ldb y) { if (top-hea<1) { top++;dx[top]=x;dy[top]=y;return ; } while (top-hea>0&&cala(x,y,dx[top],dy[top],dx[top-1],dy[top-1])) top--; top++;dx[top]=x;dy[top]=y; } int main() { int i,j,n,k,now,pre; scanf("%d%d", &n, &k); for (i=1;i<=n;i++) scanf("%I64d", &t[i]); t[0]=0ll;sum[0]=sump[0]=sumq[0]=0.0; for (i=1;i<=n;i++) { sum[i]=sum[i-1]+1.0*t[i]; sumq[i]=sumq[i-1]+1.0/t[i]; sump[i]=sump[i-1]+sum[i]*1.0/t[i]; } now=pre=0; for (i=0;i<=n;i++) dp[now][i]=sump[i]; for (i=2;i<=k;i++) { pre=now;now^=1;hea=1;top=0; for (j=i;j<=n;j++) { add(sum[j-1],sum[j-1]*sumq[j-1]-sump[j-1]+dp[pre][j-1]); while (top-hea>0&&sumq[j]*(dx[hea]-dx[hea+1])<=dy[hea]-dy[hea+1]) hea++; dp[now][j]=sump[j]-dx[hea]*sumq[j]+dy[hea]; } } printf("%.15f\n", (db)dp[now] ); return 0; }
相关文章推荐
- C++ Learning——Build a simple&little RB_Tree
- 为什么涨工资的是我和他~~因为看重,所以优待
- MVC自带的校验
- CodeForces 592D Super M
- Android图片缓存
- 可视区域判断
- SDUT 3386 小雷的冰茶几
- JOptionPane 对话框
- TypeError:this.K is undefined
- 插楼:(两款工具,帮你用好数据库)
- 如何在Eclipse中生成Native类对应的JNI的.h文件
- 顺序栈的基本操作:初始化、进栈、出栈、读栈顶元素
- 转圈打印二维数组
- 字符集,索引,视图,存储过程函数,变量,条件,光标,流程,事件,触发器
- Java千百问_06数据结构(013)_数组如何传递
- 左旋(右旋)字符串
- mysql使用distinct注意事项
- 为什么我们给父母的耐心总是那么少?
- 十 传感器
- 解决:java.sql.SQLException: 不能在 UTF8 和 UCS2 之间转换: failUTF8Conv