一,本体数据较大,且第二道测试集来到了80000条数据,每条数据均过亿,所以采用最保守的大类型unsigned long long来存储数据;并且本体限时1s中,暴力的方法肯定不行,所以可以在内存上花点功夫;
二,定义两条栈,一条数据单调栈,一条临时栈,临时栈随每次遍历时的‘i’变量更变而更新;
三,单调栈中,每个较大元素会压碎(删除)该指针下一位的较小元素,重复此过程直到下一位大于此位数据;默认每位数据id为1,既题中的个体数本身,然后该数据压碎了多少位,表示他可以看到的牛头个数,(当然不能包括自己),所以我利用w来存储他所压碎的数位,然后在此位入栈后将w赋值给他的id,来记录他所能看到的牛头,便于下一位更高的牛可以快速在此单调栈中获得自己所能看到的牛头。最后循环完之后,用op来取和可以看到的牛头总数,记得在w相加时-1,既减去本身,因为自己不能看到自己(现实中确实看不到自己吧o.O)
四,值得注意的是,每次我会利用qq来判断是否有压碎的情况出现,既出现高牛看到矮牛,因为此时单调栈中会有数值的减少,既top指针会--,只有这样我才能统计可以看到的牛头数,避免不必要的时长浪费,统计完后记得将qq重新赋值为0方便下一次判断。
五,最后不要忘记题目是采用倒序将牛牛们压入栈中,不然就会像本码喽一样对着代码调试数据集一个多小时搞不清楚哪里出错了。QWQ(所以审题最重要!)
Ac代码如下:
#include<stdio.h>
#include<stdlib.h>
typedef struct
{
unsigned long long val;
unsigned long long id;
}stack;
const int N=100005;
stack str[N];
unsigned long long a[N];
int top=-1;
unsigned long long w,qq;
unsigned long long op=0;
stack tem;
void push(stack tem)
{
str[++top]=tem;
}
void pop()
{
w+=str[top].id;
str[top--];
}
int main()
{
int n,i;
scanf("%llu",&n);
for(i=n;i>=1;i--)
{
scanf("%llu",&a[i]);
}
for(i=1;i<=n;i++)
{
w=1;
tem.val=a[i],tem.id=1;
while(top!=-1&&tem.val>str[top].val)
{
pop();
qq=1;
}
push(tem);
if(qq==1)
{
str[top].id=w;
op+=w-1;
qq=0;
}
}
printf("%llu",op);
return 0;
}