A题:
#include <iostream>
#include <cstdio>
#include <algorithm>
#define N 4013
using namespace std;
long long sum[N*N];
int binsearch (long long a[], int n, int key);
int main()
{
int n;
long long ans = 0;
cin>> n;
int a[N], b[N], c[N], d[N];
for (int i=0; i<n; i++)
cin>>a[i]>>b[i]>>c[i]>>d[i];
for(int i=0; i<n; i++){
for (int j=0; j<n; j++){
sum[i*n+j] = c[i]+d[j];
}
}
//for (int i=0; i<n*n; i++) cout <<sum[i] <<endl;
sort(sum, sum+n*n);
long long temp;
for (int i=0; i<n; i++){
for (int j=0; j<n; j++){
temp = -1*(a[i]+b[j]);
ans += binsearch(sum, n*n, temp);
}
}
cout << ans << endl;
return 0;
}
int binsearch (long long a[], int n, int key)
{
int left = 0, right = n, mid, num;
while (left <= right){
mid = (left+right)/2;
if (a[mid] == key){
num = 1;
for(int i=mid-1; i>-1&&a[i] == key; i--) num++; //①
for(int i = mid+1; i<n&&a[i] == key; i++) num++;
return num;
}
if(a[mid] < key) left = mid + 1;
if (a[mid] > key) right = mid - 1;
}
return 0;
}
各种手残加脑残,都快WA哭了
![大哭](http://static.blog.csdn.net/xheditor/xheditor_emot/default/wail.gif)
①刚开始没加这几句,忽略了数组num中可能出现相等的情况,后来加上了,但是①这一行的i--又被我手残写成i++了。。。。
B题:
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
const int N = 100013;
int a[N];
int n,c;
bool Isok (int m)
{
int next, last = 0;
for (int i=1; i<c; i++){ //①
next = last + 1;
while( next < n && a[next] - a[last] < m) next ++;
//cout << next <<endl;
if (next >= n) return false;
last = next;
}
return true;
}
int main()
{
scanf("%d %d",&n, &c);
for (int i=0; i<n; i++)
scanf("%d", &a[i]);
sort(a, a+n);
int left = 0, right = a[n-1] + 1;
int mid, ans = 0;
while (left <= right){
mid = (left + right) >> 1;
//printf ("left=%d right=%d mid=%d\n",left,right,mid);
if(Isok(mid)) {
ans = mid;
left = mid + 1;
}
else right = mid - 1;
}
printf ("%d\n", ans);
return 0;
}
①:第一个点是已经固定了放在0位置,所以循环从i =1,开始;
C题:
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
int n, k;
const int N = 100013;
int a[N];
int ans;
bool Isok (int m)
{
int sumt = 0;
for (int i=n-1; i>-1; i--){
if(a[i] > m){
if ((a[i] - m)%(k-1)) //①
sumt += (a[i] - m)/(k - 1) + 1;
else sumt += (a[i] - m)/(k - 1);
}
if (sumt > m) return false;
}
//printf ("1\n");
return true;
}
int main()
{
while (~scanf("%d", &n)){
for (int i=0; i<n; i++)
scanf("%d", &a[i]);
scanf("%d", &k);
sort(a, a+n);
if (k <= 1)
{
printf ("%d\n", a[n-1]);
continue ;
}
int left = 0, right = a[n-1]+1;
int mid;
ans = 0;
while (left <= right)
{
mid = (left + right) >> 1;
//printf ("m=%d\n", mid);
if (Isok(mid)) {
//printf ("ans = %d\n",mid);
ans = mid;
right = mid -1;
}
else left = mid + 1;
}
printf ("%d\n", ans); //②
}
return 0;
}
①:这里干燥第i件衣服用吹风机时间time = (a[i] - m) / k, 取上界,不仅仅是+1;
②:手残, 把 mid 输出了;
D题:
WA到吐了,参考了一下别人的程序。
原文链接:http://blog.csdn.net/polossk/article/details/25406653;
又是一个浮点数的二分题。题意是这样的,给n个木头棒子,然后他们的长度是l_i,分成k个等分,不允许边角料的拼接。求分成k等分之后的每份长度。
关键还是精度的问题。怎么说呢,因为浮点数的二分毕竟是与整数有区别的。这个区别又特别的恶心,就是搞不出来到底精度差在哪里,那后就不断的尴尬。。。
有一个解决这类浮点数二分的技巧,就是转化成整数的二分,同时新增一个res用于维护当前最大(小)限能够满足的题目要求的值。然后就是不断地更新左边界右边界,同时维护res就行了,当然最后返回res,确保精度。
这个题我放两份代码,分别是直接浮点数二分的(G++与C++分别提交均通过),还有整数二分的。
浮点二分法:
/****
*@author Shen
*@title poj 1064
*/
#include <cstdio>
#include <cmath>
#include <algorithm>
using namespace std;
const double eps = 1e-5;
int n, k;
double l, v[10005];
double maxa = 0;
bool test(double x)
{
int sum = 0;
for (int i = 0; i < n; i++)
sum += int(v[i] / x);
return sum >= k;
}
double Bsearch(double l, double r)
{
while (r - l > eps)
{
double mid = (r + l) * 0.5;
if (test(mid))
l = mid;
else r = mid;
}
return r;
}
void solve()
{
maxa = 0;
for (int i = 0; i < n; i++)
{
scanf("%lf", &l);
v[i] = l;
maxa = max(maxa, v[i]);
}
double ans = Bsearch(0.0, maxa);
ans = 0.01 * int(ans * 100);
//G++
printf("%.2f\n", ans);
//C++
// printf("%.2lf\n", ans);
}
int main()
{
while (~scanf("%d%d", &n, &k))
solve();
return 0;
}
整数二分法:
/****
*@author Shen
*@title poj 1064
*/
#include <cstdio>
#include <cmath>
#include <algorithm>
using namespace std;
const double eps = 1e-5;
int n, k;
double l, v[10005];
double maxa = 0;
bool test(int x)
{
int sum = 0;
for (int i = 0; i < n; i++)
sum += int(v[i] / x);
return sum >= k;
}
int Bsearch(int l, int r)
{
int res = 0;
while (l <= r)
{
int mid = (r + l) / 2;
//printf("l = %d, r = %d, mid = %d, res = %d.\n", l, r, mid, res);
if (test(mid))
res = max(res, mid), l = mid + 1;
else r = mid - 1;
}
return res;
}
void solve()
{
maxa = 0;
for (int i = 0; i < n; i++)
{
scanf("%lf", &l);
l *= 100.0;
v[i] = l;
maxa = max(maxa, v[i]);
}
int ans = Bsearch(1, int(maxa));
printf("%d.%02d\n", ans / 100, ans % 100);
}
int main()
{
while (~scanf("%d%d", &n, &k))
solve();
return 0;
}
E题
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int MaxN = 50000 + 11;
int a[MaxN];
int l,n,M;
int rm[MaxN];
bool Isok (int mid);
int main()
{
scanf("%d%d%d", &l, &n, &M);
a[0] = 0;
a[n+1] = l;
for (int i=1; i<=n; i++)
scanf("%d", &a[i]);
sort (a, a+n+2);
int left = 0, right = l + 1, mid;
int ans = 0;
while (left <= right){
mid = (left + right) >> 1;
//printf ("mid=%d\n",mid);
if (Isok(mid)){
left = mid + 1;
ans = mid;
}
else right = mid - 1;
}
printf ("%d\n", ans);
return 0;
}
bool Isok (int mid)
{
int cnt = 0, j;
memset (rm, 0, sizeof(rm));
for (int i=1; i<n+1; i++){
j = i - 1;
while (rm[j]) j--;
if (a[i]- a[j] < mid){
cnt ++;
rm[i] = 1;
}
if (cnt > M) return false;
}
j = n;
while (rm[j]) j--;
while (a[n+1] - a[j] < mid){
cnt ++;
rm[j] = 1;
while(rm[j]) j--;
}
if (cnt > M) return false;
return true;
}
虽然一次过了,但还是帖出来吧,第一次写的时候忘记sort了。