codeforece Round#311 BCDE
B题
给我们n,m , m表示茶壶的容量
接下来2*n个数字,表示茶杯的容量,将这些茶杯分给n个男孩和n个女孩
可以倒x毫升的茶水给每个女孩,那么就要倒2x毫升的茶水给男孩,当然了,茶杯要装的下,且茶壶的水足够多
问最多能倒多少毫升?
思路:将茶杯按容量从下到大排序,那么前n个茶杯一定分给女孩,后n个茶杯分给男孩。那么只要将第一个茶杯的容量作为上界,0作为下界,二分枚举x,
每次统计后n个茶杯的容量是不是>=2x,如果是,那么说明该容量是可行的。 但是最终的数据测试却错了, 因为精度要达到1e-11才能正确,不知道为什么
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <algorithm>
#include <iostream>
#include <queue>
#include <stack>
#include <vector>
#include <map>
#include <set>
#include <string>
#include <math.h>
using namespace std;
#pragma warning(disable:4996)
typedef long long LL;
const int INF = <<;
const double eps = 1e-;
/* */
int a[ + ];
int main()
{
int n, w;
while (scanf("%d%d", &n,&w) != EOF)
{
int m = * n;
for (int i = ; i < m; ++i)
{
scanf("%d", &a[i]);
}
sort(a, a + m);
double low = , high = a[], mid;
int cnt;
double tmp;
while (high - low >= eps)
{
mid = (high + low) / ;
cnt = ;
for (int i = ; i < m; ++i)
if (mid * <= a[i])
cnt++;
if (cnt >= n)
{
tmp = mid * * n;
if (tmp<w)
high = mid;
else
low = mid;
}
else
high = mid;
}
printf("%f\n", mid * * n); }
return ;
}
比完看了别人代码才知道,有更简单的方法, 只要去w/3/n, a[0], a[n]/2 的最小值就好了
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <algorithm>
#include <iostream>
#include <queue>
#include <stack>
#include <vector>
#include <map>
#include <set>
#include <string>
#include <math.h>
using namespace std;
#pragma warning(disable:4996)
typedef long long LL;
const int INF = <<;
const double eps = 1e-;
/* */
int a[ + ];
int main()
{
int n, w;
double ans = ;
while (scanf("%d%d", &n,&w) != EOF)
{
int m = * n;
for (int i = ; i < m; ++i)
{
scanf("%d", &a[i]);
}
sort(a, a + m);
ans = (double)w / / n;
ans = min(ans, (double)a[]);
ans = min(ans, (double)a[n] / );
printf("%lf", ans**n);
}
return ;
}
C题
给我们n,表示有n条桌腿,
然后接下来n个数字,Li表示桌腿的长度,
再接下来n个数组,di表示砍掉第i的桌腿的费用。
一个桌子要是稳定的,要求桌子最长的桌腿的条数占总条数的一半以上
问使得桌子稳定的最小花费
思路:将桌腿按长度排序,然后遍历桌腿,枚举桌腿的长度x作为最长的桌腿,那么比x长的桌腿应该去掉,
比x长的桌腿都排在x后面,所以我们可以维护一个后缀和,使得可以在O(1)的时间内获得砍掉比x长的所有桌腿的费用
设长度为x的桌腿有cnt条,那么要将比x短的桌腿砍掉剩下cnt-1条即可。 砍的时候,肯定是先砍费用小的。
比赛时的想法是用优先队列维护一个费用队列,队头的费用最小。但是时间复杂度超了(不去算算法的时间复杂度果然是不好的习惯)
其实费用的取值是1-->200,所以只要用个标记数组来标记,每次只要遍历标记数组就可以了。
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <algorithm>
#include <iostream>
#include <queue>
#include <stack>
#include <vector>
#include <map>
#include <set>
#include <string>
#include <math.h>
#include <functional>
using namespace std;
#pragma warning(disable:4996)
typedef long long LL;
const int INF = <<;
/* */
const int N = + ;
struct Node
{
int l, d;
bool operator<(const Node&rhs)const
{
return l < rhs.l;
}
}a[N];
int suffix[N],c[N];
void input(int &x)
{
char ch = getchar();
while (ch < '' || ch>'')
ch = getchar();
x = ;
while (ch >= '' && ch <= '')
{
x = x * + ch - '';
ch = getchar();
}
}
int main()
{
int n, i, j, ans, k, total;
while (scanf("%d", &n)!=EOF)
{
total = ;
for (i = ; i < n; ++i)
input(a[i].l);
for ( i = ; i < n; ++i)
input(a[i].d); sort(a, a + n);
for (i = ; i < n; ++i)
suffix[i] = a[i].d;
for (i = n - ; i >= ; --i)
suffix[i] += suffix[i + ];
i = ;
ans = INF;
while (i < n)
{
int tmp = a[i].l;
j = i;
while (i < n && a[i].l == tmp)
i++;
int cnt = i - j;
tmp = ;
//砍掉比x更长的桌腿
if (i<n)
tmp = suffix[i];
//total统计的是比x短的桌腿条数
int t = total; for (k = ; k <= ; ++k)
{
if (t < cnt)
break;
if (t - c[k] >= cnt - )
{
tmp += c[k] * k;
t -= c[k];
}
else
{
tmp += k * (t - cnt + );
break;
}
} for (k = j; k < i; ++k)
{
c[a[k].d]++;
total++;
}
ans = min(ans, tmp);
}
printf("%d\n", ans);
}
return ;
}
D题:
给定一个图,问最少要加多少条边才使得图有长度为奇数的环。并输出方案数。
第一种情况:如有m=0,那么考虑一个环最少有3个点,3条边,所以我们要从n个点中选3个点,并且加上3条边就可以形成环
方案书是C(n,3)
第二种情况:每个点的度数不超过1(即图的最大连通分量只有2个点),那么只要加2条边,且方案数为 2个点的连通分量加独立的点形成的方案数(n-2*m)*n
+ 2个点的连通分量加2个点的连通分量所形成环的方案书 2*m(m-1)
第三种情况:那么肯定最大连通分量有3个点,那么只要加1条边就可以了。所以只要将图染色,将黑色的点,或者白色的点连起来就形成环了
方案数是所有连通分量的 C(黑色,2) + C(白色,2)
当然了,如果图本身就存在奇数环, 那么输出0 1 就好了
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <algorithm>
#include <iostream>
#include <queue>
#include <stack>
#include <vector>
#include <map>
#include <set>
#include <string>
#include <math.h>
using namespace std;
#pragma warning(disable:4996)
typedef long long LL;
const int INF = <<;
/* */
const int N = + ;
vector<int> g[N];
int d[N];
int color[N];
bool hasOddCycle;
void dfs(int u, int fa,int &cnt, int &black)
{ for (int i = ; i < g[u].size(); ++i)
{
int v = g[u][i];
if (v == fa) continue;
if (color[v] == -)
{
color[v] = color[u] ^ ;
black += color[v];
cnt += ;
dfs(v, u, cnt, black);
}
else if (color[u] == color[v])
{
hasOddCycle = true;
} }
}
int main()
{
int n, m, a, b;
bool flag = false;
scanf("%d%d", &n, &m);
if (m == )
{
printf("%d %I64d\n", , (LL)n*(n - )*(n-) / );
return ;
}
for (int i = ; i < m; ++i)
{
scanf("%d%d", &a, &b);
g[a].push_back(b);
g[b].push_back(a);
d[a]++;
d[b]++;
if (d[a]> || d[b] > )
flag = true;
}
if (!flag)
{
printf("%d %I64d\n", , (LL)(n - * m)*m + (LL) * m*(m - ));
return ;
}
memset(color, -, sizeof(color));
LL ans = ;
int cnt, black;
for (int i = ; i <= n; ++i)
{
if (color[i] == -)
{
cnt = black = ;
color[i] = ;
dfs(i, -, cnt, black);
ans += (LL)black*(black - ) / + (LL)(cnt - black)*(cnt - black - ) / ;
}
if (hasOddCycle)
break;
}
if (hasOddCycle)
printf("%d %d\n", , );
else
printf("%d %I64d\n", , ans); return ;
}
E题:
用dp的方法在O(n*n)的时间内求出所有的half-palindrome. 然后将所有的子串都插入字典树中,时间复杂度同样是O(n*n),然后dfs到第k个half-palindrome
dfs的时间复杂度同样是O(n*n),因为字典树的节点数不超过O(n*n)
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <algorithm>
#include <iostream>
#include <queue>
#include <stack>
#include <vector>
#include <map>
#include <set>
#include <string>
#include <math.h>
using namespace std;
#pragma warning(disable:4996)
typedef long long LL;
const int INF = <<;
/*2 */
int root, size, k, m = -;
const int N = + ;
bool ok[N][N];
char str[N], ans[N];
struct Trie
{
int cnt, next[];
void init()
{
cnt = ;
next[] = next[] = -;
}
}trie[N*N]; void add(int i, int n)
{
int cur = root;
for (int j = i; j < n; ++j)
{
if (trie[cur].next[str[j] - 'a'] == -)
{
trie[size].init();
trie[cur].next[str[j] - 'a'] = size++;
}
cur = trie[cur].next[str[j] - 'a'];
if (ok[i][j])
trie[cur].cnt++;
}
}
void dfs(int cur)
{
k -= trie[cur].cnt;
if (k <= )
{
printf("%s\n", ans);
exit();
}
for (int i = ; i < ; ++i)
{
if (trie[cur].next[i] != -)
{
ans[++m] = 'a' + i;
dfs(trie[cur].next[i]);
ans[m--] = ;
}
}
}
int main()
{
scanf("%s%d", str,&k);
int n = strlen(str);
size = ;
trie[root].init();
for (int len = ; len <= n; ++len)
{
for (int i = ; i <= n - len; ++i)
{
int j = i + len - ;
if (j - i <= )
ok[i][j] = str[i] == str[j];
else
ok[i][j] = str[i] == str[j] && ok[i + ][j - ];
}
}
for (int i = ; i < n; ++i)
add(i, n);
dfs(root);
return ;
}
codeforece Round#311 BCDE的更多相关文章
- Codeforces Round #311 (Div. 2) E. Ann and Half-Palindrome 字典树/半回文串
E. Ann and Half-Palindrome Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/contes ...
- Codeforces Round #311 (Div. 2) D. Vitaly and Cycle 图论
D. Vitaly and Cycle Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/contest/557/p ...
- Codeforces Round #311 (Div. 2) C. Arthur and Table Multiset
C. Arthur and Table Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/contest/557/p ...
- Codeforces Round #311 (Div. 2)B. Pasha and Tea 水题
B. Pasha and Tea Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/contest/557/prob ...
- Codeforces Round #311 (Div. 2) A. Ilya and Diplomas 水题
A. Ilya and Diplomas Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/contest/557/ ...
- Codeforces Round #311 (Div. 2) D. Vitaly and Cycle 奇环
题目链接: 点这里 题目 D. Vitaly and Cycle time limit per test1 second memory limit per test256 megabytes inpu ...
- Codeforces Round #311 (Div. 2) D - Vitaly and Cycle(二分图染色应用)
http://www.cnblogs.com/wenruo/p/4959509.html 给一个图(不一定是连通图,无重边和自环),求练成一个长度为奇数的环最小需要加几条边,和加最少边的方案数. 很容 ...
- Codeforces Round #311 (Div. 2) E - Ann and Half-Palindrome(字典树+dp)
E. Ann and Half-Palindrome time limit per test 1.5 seconds memory limit per test 512 megabytes input ...
- Codeforces Round #311 (Div. 2)
我仅仅想说还好我没有放弃,还好我坚持下来了. 最终变成蓝名了,或许这对非常多人来说并不算什么.可是对于一个打了这么多场才好不easy加分的人来说,我真的有点激动. 心脏的难受或许有点是由于晚上做题时太 ...
随机推荐
- Matlab的parfor并行编程
Matlab的parfor并行编程 通常消耗最多计算资源的程序往往是循环. 把循环并行化.或者优化循环体中的代码是最经常使用的加快程序执行速度的思路. Matlab提供了parforkeyword,能 ...
- c++ anonymous union,struct -- 匿名联合体和机构体
c++ anonymous union,struct -- 匿名联合体和机构体 结构体和联合体各自的基本用法不赘述,仅说一下他们匿名时访问的情况.如果是token不同,可以直接跨层访问.例子 #inc ...
- [C#基础] 类
类成员 字段和方法是最重要的类成员类型,字段是数据成员,方法是函数成员 字段 字段是隶属于类的变量 它可以是任何类型,无论是预定义类型还是用户定义类型 和所有变量一样,字段用来保存数据 它们可以被写入 ...
- 与众不同 windows phone (30) - Communication(通信)之基于 Socket TCP 开发一个多人聊天室
原文:与众不同 windows phone (30) - Communication(通信)之基于 Socket TCP 开发一个多人聊天室 [索引页][源码下载] 与众不同 windows phon ...
- java输出换行的标准姿势"line.separator"
java中写.txt文件,实现换行的几种方法: 1.使用java中的转义符"\r\n": windows下的文本文件换行符:\r\n linux/unix下的文本文件换行符:\r ...
- Linux vmstat命令详解
vmstat命令是最常见的Linux/Unix监控工具,可以展现给定时间间隔的服务器的状态值,包括服务器的CPU使用率,内存使用,虚拟内存交换情况,IO读写情况.这个命令是我查看Linux/Unix最 ...
- TControl的消息覆盖函数大全(15个WM_函数和17个CM_函数,它的WndProc就处理鼠标与键盘消息)
注意,这些函数只有Private一种形式(也就是不允许覆盖,但仍在动态表格中)(特别注意,这里居然没有WM_PAINT函数): TControl = class(TComponent) private ...
- 解析android framework下利用app_process来调用java写的命令及示例
解析android framework下利用app_process来调用java写的命令及示例 在android SDK的framework/base/cmds目录下了,有不少目录,这些目的最终都是b ...
- Linux 技巧之 Grub 超实用技巧
1. 简单介绍 什么是 GRUB?GRUB 全名Grand Unified Boot Loader,它是一个引导装入器 -- 它负责装入内核并引导 Linux 系统.GRUB 还能够引导其他操作系统, ...
- C#之自己定义的implicit和explicit转换
在类型转换时常会遇到隐式转换和显式转换.那我们自己定义的类型要怎样去定义隐式转换和显式转换?我们来看一段代码 public class Rational { private Int32 _inner_ ...