主题:第51次编程比赛
renew [专家分:200] 发布于 2007-03-22 18:02:00
题目:训练场上n(1≤n≤50000)个[b][color=FF0000]高矮都不相同[/color][/b]的士兵[b]从左到右[/b]排成一行,依次编号为1,2,…,n。第i个士兵的身高H(i),由于采用特殊单位,H(i)满足1≤H(i)≤2000000000。设第i个士兵右侧最近的比他个高的士兵编号为j,则第i个士兵可看到在他的右侧比他矮的士兵的个数S(i)=j-i-1。(不考虑客观因素,比如视力范围等-,-)
求S(1)+S(2)+…+S(n)。
输入:
标准输入。
第一行为整数n,表示士兵的个数。
第二行n个整数,用一个空格隔开。分别表示编号为1,2。。。n的士兵的身高
输出:
S(1)+S(2)+…+S(n)的结果
例:
输入
6
10 3 7 4 12 2
输出
5
例子说明:
S(1) = 3
S(2) = 0
S(3) = 1
S(4) = 0
S(5) = 1
S(6) = 0
S(1)+S(2)+S(3)+S(4)+S(5)+S(6) = 3+0+1+0+1+0 = 5
最后更新于:2007-03-26 00:19:00
回复列表 (共65个回复)
51 楼
opensky5 [专家分:0] 发布于 2007-03-24 17:24:00
#include<iostream>
using namespace std;
long n;
long long heigh[50000];
long long total[50000];
int main()
{
scanf("%d",&n);
for (long a=1;a<=n;++a) scanf("%ld",&heigh[a]);
total[n]=0;
long b=0;
for (long a=n-1;a>=1;--a)
{
if (heigh[a]>heigh[a+1]) b=total[a+1]+a+1;else b=a+1;
while ((heigh[a]>heigh[b])&&(b<=n)) ++b;
total[a]=b-a-1;
}
long long ans=0;
for (long a=1;a<=n;++a) ans+=total[a];
printf("%ld",ans);
}
52 楼
fjqqj [专家分:90] 发布于 2007-03-24 18:18:00
#include <stdio.h>
#include <stdlib.h>
/*#include <time.h>*/
#define M 50000 /* 士兵人数 */
void arrin(unsigned long int *H)
{
int i=0,j,x;
while(i<M)
{
/*srand((unsigned)time(NULL)); 初始化随机种子*/
x=(rand()%10000+1)*(rand()%10000+1)*(rand()%20+1); /*随机输出士兵身高*/
j=0;
while((j<i)&&(x!=H[j]))
j++;
if(j==i) H[i++]=x;
}
}
/*输出H(i)身高。
void arrout(unsigned long int *H)
{
int i;
for(i=0; i<M; i++)
printf("%-20d",H[i]);
printf("\n");
}
*/
void arrsum(unsigned long int *H,unsigned int *S,unsigned int sum)
{
unsigned int i=0,j;
while(i<M)
{
for(j=i+1; j<M; j++)
if(H[i]<H[j]) break;
S[i]=j-i-1;
sum+=S[i];
i++;
}
printf("Sum=%d\n",sum); /*输出S(n)总和*/
}
int main(void)
{
unsigned long int H[M]={0},sum=0; /*H[M]是士兵身高,sum是能看到右侧士兵的总和*/
unsigned int S[M]; /*S[M]是第i个士兵能看到右侧士兵的个数*/
/*int start,finish;*/
/*start=clock();开始时间*/
arrin(H); /*随机输入士兵H(i)身高*/
/*arrout(H);输出H(i)身高。*/
arrsum(H,S,sum); /*输出能看到右侧士兵的总和*/
/*finish=clock();结束时间*/
/*printf("Time:%dms\n",finish-start);运行时间*/
system("pause");
return 0;
}
53 楼
hwjian [专家分:0] 发布于 2007-03-24 20:23:00
int CountShort(int n,int height[])
{
int *s=new int[n];
memset(s,0,n*sizeof(int));
for(int i=n-2;i>=0;i--)
for(int k=i+1;k<=n-1;)
{
if(height[i]>height[k])
{
s[i]+=(s[k]+1);
k+=(s[k]+1);
}
else
break;
}
delete s;
int sum(0);
for(int i=0;i<n;i++)
sum+=s[i];
return sum;
}
54 楼
zhjh008 [专家分:700] 发布于 2007-03-24 22:29:00
#include <iostream>
using namespace std;
unsigned int S = 0;
unsigned int H[50000];
int main(int argc, char* argv[])
{
int n;
cin>>n;
for(int i=0;i<n;i++)
{
cin>>H[i];
for(int j=i-1;j>=0;j--)
{
if(H[j])
{
if(H[j] > H[i])
S += 1;
else
H[j] = 0;
}
}
}
cout<<S<<endl;
return 0;
}
55 楼
ongday [专家分:0] 发布于 2007-03-25 01:50:00
#include<stdio.h>
main()
{
unsinded int i,j,m;
double flout H[50000],s[50000],S;
printf("输入士兵个数及每个士兵身高。\n");
scanf("%d",&i); /*输入士兵个数*/
printf("\n");
for(m=1;m<=i;m++) /*输入士兵身高*/
scanf("%d "&H[i-1]);
for(m=1;m<=i;m++)
{fou(j=1;j<=i;j++)
if(H[j-1]>H[i-1]) /*计算*/
break;
s(i-1)=j-i-1;
}
for(S=0,m=1;m<=i;m++)
S=S+s(i-1);
printf("%d",S); /*输出结果*/
}
56 楼
yxs0001 [专家分:9560] 发布于 2007-03-25 10:00:00
int Insert(int n,int height[],int num)
{
int low = 0,high = n-1;
while(low<=high){
int m = (low + high) / 2;
if(height[m] > num)
low = m + 1;
else
high = m - 1;
}
return high + 1;
}
int countHeight(int n,int height[])
{
const int Max = 50000; //最大士兵数
int temp[Max]; //保存递减序列
temp[0] = height[0];
int Up = 0; //序列的上界
int result = 0; //返回值
for(int i = 1;i<n;i++){
if(height[i]>temp[0]) //下一个士兵高度大于序列中任一高度
Up = 0;
else if(height[i]<temp[Up]) //下一个士兵高度小于序列中任一高度
++Up;
else //下一个士兵高度在序列中
Up = Insert(Up+1,temp,height[i]);
result += Up;
temp[Up] = height[i];
}
return result;
}
57 楼
小黑骑DK [专家分:610] 发布于 2007-03-25 11:39:00
//这下楼主要辛苦了,交卷的人那么多,而且这个题目还不好测试。
//对于{10, 3, 9, 2, 8, 4, 5};结果应为6+0+4+0+2+0=12,但是我下面注释起来的那个版本是8。
//楼主最好找几个帮手测试哦。
unsigned long Num_soldier_see(long total, long *height)
{
static long *first[49998] = {0};//用malloc怕速度慢,不过49998写得我慌
unsigned long sum = 0;
long *second = height;
long *third = height + 1;
long NumCountinue = 0;
long endPosition = -1;//记录在second前面的元素个数
while (third != height + total)
{
if (*second > *third)
{
sum += ++NumCountinue;
first[++endPosition] = second++;
third++;
}
else
{
while (endPosition != -1)
{
if ( *(first[endPosition]) > *third)
{
NumCountinue = endPosition + 1;
sum += NumCountinue;
second = third++;
break;
}
else
{
endPosition--;
}
}
if (endPosition == -1)
{
NumCountinue = 0;
second = third++;
}
}
}
return sum;
}
/*
错误 !
unsigned long Num_soldier_see(long total, long *height)
{
unsigned long sum = 0;
long *first = height;
long *second = height;
long *third = height + 1;
long NumCountinue = 0;
while (third != height + total)
{
if (*second > *third)
{
sum += ++NumCountinue;
second++;
third++;
}
else
{
if (*first > *third)
{
NumCountinue = 1;
sum += 1;
second = third++;
}
else
{
first = second = third++;
NumCountinue = 0;
}
}
}
return sum;
}*/
58 楼
小黑骑DK [专家分:610] 发布于 2007-03-25 12:35:00
我是57楼的,我的要改一下。
那个49998要改49999。。。
或者直接50000算了, 都50000了也不差那一点了。。。
59 楼
eastcowboy [专家分:25370] 发布于 2007-03-25 14:31:00
#include <stdio.h>
#include <stdlib.h>
// 起用以下语句,可以进入测试模式。使用两种不同算法计算结果,并判断改进算法是否有错
// 禁用以下语句,则为正式模式,提交用。
// #define TEST
#ifdef TEST
// cal_safe
// 采用保守算法,尽量追求正确
int cal_safe(int nSolders, const int* iHeight)
{
int ret = 0;
int i, j;
for(i=0; i<nSolders; ++i)
{
for(j=i+1; j<nSolders && iHeight[i] > iHeight[j]; ++j)
{
++ret;
}
}
return ret;
}
#endif
// cal_fast
// 改进的算法,尽量追求快速
int cal_fast(int nSolders, const int* iHeight)
{
int ret = 0;
int i, j, k;
int* tmp = (int*)calloc(nSolders, sizeof(int));
int tmp_count = 0;
// 检查所有士兵,将身高比左边一个高的记录到数组tmp中
for(i=1; i<nSolders; ++i)
if( iHeight[i] > iHeight[i-1] )
tmp[tmp_count++] = i;
// 对每一士兵,只检查右边所有身高有增高趋势的士兵
k = 0;
for(i=0; i<nSolders; ++i)
{
while( k < tmp_count && tmp[k] < i )
++k;
for(j=k; j<tmp_count; ++j)
{
if( iHeight[i] < iHeight[tmp[j]] )
break;
}
if( j<tmp_count )
ret += (tmp[j]-i-1);
else
ret += nSolders-i-1;
}
free(tmp);
return ret;
}
int main(void)
{
#ifndef TEST
int nSolders, i;
int* iHeight;
scanf("%d", &nSolders);
iHeight = (int*)malloc(nSolders*sizeof(int));
for(i=0; i<nSolders; ++i)
scanf("%d", &(iHeight[i]));
printf("%d\n", cal_fast(nSolders, iHeight));
free(iHeight);
#else
int nSolders;
static int iHeight[50000];
int samples, i;
int nError = 0;
for(samples=0; samples<1000; ++samples)
{
int a, b;
nSolders = rand() % 50000 + 1;
// 取得nSolders个不同的数值作为身高
for(i=0; i<nSolders; ++i)
iHeight[i] = i + 1;
for(i=0; i<1000; ++i)
{
int tmp;
a = rand() % nSolders;
b = rand() % nSolders;
tmp = iHeight[a];
iHeight[a] = iHeight[b];
iHeight[b] = tmp;
}
// 两种方式计算结果
a = cal_safe(nSolders, iHeight);
b = cal_fast(nSolders, iHeight);
if( a != b )
{
printf("error.\n");
++nError;
}
}
printf("there are %d error(s).\n", nError);
#endif
return 0;
}
60 楼
jia4082 [专家分:0] 发布于 2007-03-25 18:38:00
#include "stdio.h"
typedef unsigned int U32;
enum
{
ERR_OK,
ERR_PARAM,
};
int P51(int n, U32 *height);
void main()
{
/* int n = 6;
U32 height[] = {10, 3, 7, 4, 12, 2};
*/
int n = 20;
U32 height[] = {2000000000, 200000001, 20000001, 2000001, 200001, 20001, 2001, 201, 21, 2,
5, 2, 200002, 200001, 200000, 20000, 2000, 200, 20, 2};
P51(n, height);
}
int P51(int n, U32 *height)
{
static U32 s[50000] = {0};
U32 sum = 0;
int i = 0, j = 0;
if ((n <= 0) || (height == NULL))
return ERR_PARAM;
s[n - 1] = 0;
/* from right to left */
for (i = n - 2; i >= 0; i--)
{
/* not higher than his right */
if (height[i] <= height[i + 1])
{
s[i] = 0;
}
else /* higher than his right */
{
j = i + 1;
while ((j < n) && (height[i] > height[j]))
{
s[i] += s[j] + 1;
j += s[j] + 1;
}
sum += s[i];
}
}
printf("%u\n", sum);
return ERR_OK;
}
我来回复