Codeforces Round 311 div2
2015-07-02 08:09
260 查看
总计:
虽然被skipped了,但是也近乎独立做了两题。心情不错。
直接上B题。水题。然而比赛中交的代码是错误的,主要是输出格式问题。题目要求输出浮点数,但是没说怎么处理尾0。而cout是可以自动去除尾0的,printf就不可以。然而问题是,当ans大些时,cout会输出科学记数法,导致答案错误。而不要求精度(实际上本题要求1e-6)。这时候就是做题经验的问题了,输出的不一定要和样例完全一样,简单printf即可
C题,排序检索题,单刷很久。给一些凳子脚的长度和去除该凳子脚需要的代价。求最小代价使得最大凳子脚的个数超过剩余个数的1/2。
因为凳子脚的长度在1-200的范围内,所以想到枚举最大凳子脚。假设当前枚举的凳子脚长度为l,则需要预处理长度大于L的凳子脚都要去掉,并且长度为L的凳子脚都不能去掉(易证),在长度小于L的凳子脚中找最小代价。按照凳子脚长度排序,用sum数组统计长度大于L的代价和。
枚举长度小于L的凳子脚的时候T了。刚开始使用容器来存每种长度对应的下标。T后穷举。又T,然后想到新办法。用dd数组存所有代价的初始个数。每往下移动一个就减去当前凳子脚代价的dd数组值减一。于是过了。
找个时间补一补D和E。D好像是简单图论题,我觉得图论不能再这样水下去了。
源码:
B:
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <string>
#include <queue>
using namespace std;
const int MAXN = 1e5;
int data[MAXN*2+5];
bool cmp(int a,int b){return a<b;}
int main()
{
int n,w;
while(scanf("%d%d",&n,&w) != EOF){
for(int i=0; i<2*n; i++)
scanf("%d",&data[i]);
sort(data,data+2*n,cmp);
double ans = 0;
if(data[0] * 2 < data
){
ans = data[0];
ans = ans * 3 * n;
if(ans > w)
ans = w;
}
else{
ans = data
;
ans = ans / 2 * 3 * n;
if(ans > w)
ans = w;
}
printf("%f\n",ans);
// cout<<ans<<endl;
}
return 0;
}
C:
#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <algorithm>
#include <iostream>
#include <vector>
#define gmax(a,b) a>b?a:b
#define gmin(a,b) a<b?a:b
using namespace std;
const int MAXN = 1e5+5;
struct D
{
int l,d;
}lv[MAXN];
int dd[200+5];
bool cmp1(D a,D b)///first l up,second d down
{
if(a.l != b.l)
return a.l>b.l;
return a.d < b.d;
}
bool cmp2(D a,D b)
{
return a.d < b.d;
}
int sum[MAXN];
int main()
{
int n;
while(scanf("%d",&n) != EOF){
memset(dd, 0, sizeof(dd));
for(int i=1; i<=n; i++){
scanf("%d",&lv[i].l);
}
for(int i=1; i<=n; i++){
scanf("%d",&lv[i].d);
dd[lv[i].d]++;
}
sort(lv + 1, lv + n + 1, cmp1);
sum[0] = 0;
for(int i=1; i<=n; i++){
if(i == 1)
sum[i] = lv[i].d;
else
sum[i] = sum[i-1] + lv[i].d;
}
// int f = 1;
int pre = 0;
int ans = sum
;
int res = sum
;
// for(int i=1; i<=n; i++)
// printf("for i = %d,lv[i].d = %d,lv[i].l = %d\n",i,lv[i].d,lv[i].l);
dd[lv[1].d]--;
for(int i=2; i<=n+1; i++){
if(lv[i].l != lv[i-1].l || i == n+1){
// printf("i = %d\n",i);
int now = i - 1;
int len = n - pre - 2 * (now - pre) + 1;
// printf("i = %d,pre = %d\n",i,pre);
// printf("len = %d\n",len);
res = sum[pre];
// printf("first res = %d\n",res);
if(len <= 0){
ans = gmin(ans, res);
break;
}
for(int j=1; j<=200; j++){
if(dd[j] >= len){
res += j * len;
len = 0;
}
else{
res += dd[j] * j;
len -= dd[j];
}
if(len <= 0)
break;
}
pre = now;
}
dd[lv[i].d]--;
ans = gmin(res, ans);
}
printf("%d\n",ans);
}
return 0;
}
/*
2
1 5
3 2
*/
虽然被skipped了,但是也近乎独立做了两题。心情不错。
直接上B题。水题。然而比赛中交的代码是错误的,主要是输出格式问题。题目要求输出浮点数,但是没说怎么处理尾0。而cout是可以自动去除尾0的,printf就不可以。然而问题是,当ans大些时,cout会输出科学记数法,导致答案错误。而不要求精度(实际上本题要求1e-6)。这时候就是做题经验的问题了,输出的不一定要和样例完全一样,简单printf即可
C题,排序检索题,单刷很久。给一些凳子脚的长度和去除该凳子脚需要的代价。求最小代价使得最大凳子脚的个数超过剩余个数的1/2。
因为凳子脚的长度在1-200的范围内,所以想到枚举最大凳子脚。假设当前枚举的凳子脚长度为l,则需要预处理长度大于L的凳子脚都要去掉,并且长度为L的凳子脚都不能去掉(易证),在长度小于L的凳子脚中找最小代价。按照凳子脚长度排序,用sum数组统计长度大于L的代价和。
枚举长度小于L的凳子脚的时候T了。刚开始使用容器来存每种长度对应的下标。T后穷举。又T,然后想到新办法。用dd数组存所有代价的初始个数。每往下移动一个就减去当前凳子脚代价的dd数组值减一。于是过了。
找个时间补一补D和E。D好像是简单图论题,我觉得图论不能再这样水下去了。
源码:
B:
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <string>
#include <queue>
using namespace std;
const int MAXN = 1e5;
int data[MAXN*2+5];
bool cmp(int a,int b){return a<b;}
int main()
{
int n,w;
while(scanf("%d%d",&n,&w) != EOF){
for(int i=0; i<2*n; i++)
scanf("%d",&data[i]);
sort(data,data+2*n,cmp);
double ans = 0;
if(data[0] * 2 < data
){
ans = data[0];
ans = ans * 3 * n;
if(ans > w)
ans = w;
}
else{
ans = data
;
ans = ans / 2 * 3 * n;
if(ans > w)
ans = w;
}
printf("%f\n",ans);
// cout<<ans<<endl;
}
return 0;
}
C:
#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <algorithm>
#include <iostream>
#include <vector>
#define gmax(a,b) a>b?a:b
#define gmin(a,b) a<b?a:b
using namespace std;
const int MAXN = 1e5+5;
struct D
{
int l,d;
}lv[MAXN];
int dd[200+5];
bool cmp1(D a,D b)///first l up,second d down
{
if(a.l != b.l)
return a.l>b.l;
return a.d < b.d;
}
bool cmp2(D a,D b)
{
return a.d < b.d;
}
int sum[MAXN];
int main()
{
int n;
while(scanf("%d",&n) != EOF){
memset(dd, 0, sizeof(dd));
for(int i=1; i<=n; i++){
scanf("%d",&lv[i].l);
}
for(int i=1; i<=n; i++){
scanf("%d",&lv[i].d);
dd[lv[i].d]++;
}
sort(lv + 1, lv + n + 1, cmp1);
sum[0] = 0;
for(int i=1; i<=n; i++){
if(i == 1)
sum[i] = lv[i].d;
else
sum[i] = sum[i-1] + lv[i].d;
}
// int f = 1;
int pre = 0;
int ans = sum
;
int res = sum
;
// for(int i=1; i<=n; i++)
// printf("for i = %d,lv[i].d = %d,lv[i].l = %d\n",i,lv[i].d,lv[i].l);
dd[lv[1].d]--;
for(int i=2; i<=n+1; i++){
if(lv[i].l != lv[i-1].l || i == n+1){
// printf("i = %d\n",i);
int now = i - 1;
int len = n - pre - 2 * (now - pre) + 1;
// printf("i = %d,pre = %d\n",i,pre);
// printf("len = %d\n",len);
res = sum[pre];
// printf("first res = %d\n",res);
if(len <= 0){
ans = gmin(ans, res);
break;
}
for(int j=1; j<=200; j++){
if(dd[j] >= len){
res += j * len;
len = 0;
}
else{
res += dd[j] * j;
len -= dd[j];
}
if(len <= 0)
break;
}
pre = now;
}
dd[lv[i].d]--;
ans = gmin(res, ans);
}
printf("%d\n",ans);
}
return 0;
}
/*
2
1 5
3 2
*/
相关文章推荐
- 程序猿的福音--再也不用担心软件的bug了!?
- 【剑指Offer学习】【面试题26:复杂链表的复制】
- 判断浏览器客户端是不是移动客户端
- 插入元素到有序数组,二分搜索查找插入位置
- LLBL Gen Pro 4.2 Lite 免费的对象关系映射开发框架与工具
- Python基础知识回顾
- 算法与数据结构八日谈之二——动态规划
- nyoj 1100 WAJUEJI which home strong! 【简单BFS】
- 破解NET的四大神器
- SendInput -- 鼠标移动
- 移动端web资源
- 20 款优秀的 Linux 终端仿真器
- 《C语言陷阱与缺陷》读书笔记 之 运算符优先
- Section 12 GUI
- windows下搭建cocos2d-x环境
- rndc reload 执行过程
- virtualbox中ubuntu和windows共享文件夹设置
- 安卓棒棒糖,敲出国内ROM厂商真面目
- 开始转向互联网,后面每两周发一篇
- 基于google protobuf 的 socket udp 通信