您的位置:首页 > 其它

Re0(学长在2017新年出的题)

2017-08-06 20:18 176 查看
Problem Description



Re0 虽然是老套的穿越剧情,但是却有着虐男主 (486) 的新奇点子。作为 2016 最火的番,我们来统计一下其中每个人能看到的对手的人数吧。

对于当前的人,他只能看见战力从他依次增高的一个阶梯。譬如说对于战力分别为 6, 5, 1, 2, 3, 4, 0 的一个分布来说,第一个向前看去看到的对手人数为 0,第二个向前看去能看到战力为 6 的人,看到的对手人数为 1,第三个向前看去能看到战力为 6, 5 的 2 人,第四个向前看去能看到战力为 6, 5 的 2 人,第五个向前看去能看到战力为 6, 5 的 2 人,第六个向前看去能看到战力为 6, 5 的 2 人,第七个向前看去能看到战力为 4, 5, 6 的 3 人。而战力为 1, 2, 3 的人会被战力为 4 的人所屏蔽掉。

Input

输入数据有多组(数据组数不超过 20),到 EOF 结束。

对于每组数据:

•第一行输入一个整数 n, m 表示要统计的总人数和询问的次数。

•接下来一行有 n 个以空格分隔的正整数,表示 n 个人的战力分布。

•接下来 m 行,每行一个正整数 pos,表示要询问的人的位置,位置标号按照输入从 1~n。

数据范围:1 <= n, m <= 100000,战力范围为 1~1000。

Output

对于每组数据中的每次询问,输出一个正整数表示此人向前看去能够看到的对手(威胁)数。

Example Input

7 7

6 5 1 2 3 4 0

1

2

3

4

5

6

7

Example Output

0

1

2

2

2

2

3

Hint

Author

「SDUT Round #2 - 2017 新春大作战」UMR

Think: 一道普通栈的题。。。思考一下如何对战力高低出栈、入栈就解决问题了(读题,从本位置开始递增。。。)。直接暴力循环过的想法有点天真(出题的学长呵呵一笑)2333。看透题意后,说白了就是求每个位置,从左边看,能看到比当前位置战力高的递增战力的数目(从栈底到栈顶,战力递减的长度)。

直接上C的代码:

#include<stdio.h>
#include<string.h>
#include<malloc.h>
#define MAX 100100  //已知数据范围
typedef int Elem;
typedef struct
{
int base;  //栈底
int top;   //栈顶(实际上是+1了)
Elem *data; //战力
int length;  //栈的长度
int size;    //栈开辟的空间大小(和之前我发的栈一样,因为没有数据卡,就没有当空间不够时动态增加新空间)
}stack;
void Init(stack *s);  //初始化栈
void Push(stack *s, int k);  //入栈
void Pop(stack *s);  //弹出栈顶
int Empty(stack *s);  //判断栈是否为空
int Gettop(stack *s);  //返回栈顶元素
int main()
{
int n, m;
while(scanf("%d %d", &n, &m) != EOF){
stack s;  //定义栈s
Init(&s); //初始化栈
int i, k, h, a[100100];
memset(a, 0, sizeof(a)); //用来存第i个位置可以看到的对手数,方便询问操作,直接拿来输出
for(i = 1; i <= n; i++){
scanf("%d", &k);  //战力值
if(Empty(&s)){  //如果当前栈为空直接入栈
a[i] = s.length;  //入栈前,该位置可以看见的对手数
Push(&s, k);  //入栈
}
else{                   //这个else是本题的代码精化部分~
while(!Empty(&s)){  //如果栈不空
h = Gettop(&s); //栈顶的战力值
if(k >= h){     //如果当前位置的战力大于等于栈顶的战力,弹出栈顶,应为要求从当前位置向左看
Pop(&s);    //可以看见的递增战力(很好理解吧O(∩_∩)O哈哈~)
}
else{           //当小于栈顶的战力就入栈(所以栈其实是一个递减的战力分布)
a[i] = s.length; //本位置入栈前,本位置望左看,可以看见的递增战力的数目
Push(&s, k);
break;  //操作完成后就退出循环嘛(其实一开始自己漏了2333)
}
}
if(Empty(&s)){       //本题的隐藏关键(特殊情况),本位置的战力高于左边所有的战力!!!还好傻傻的自己在Wrang Answer后机智地想到了这点
a[i] = s.length;
Push(&s, k);
}
}
}
for(i = 1; i <= m; i++){
scanf("%d", &k);       //要询问的位置
printf("%d\n", a[k]);
}
}
return 0;
}
void Init(stack *s)
{
s->data = (Elem *)malloc(MAX * sizeof(Elem));
if(!s->data) exit(0);
s->top = s->base = 1;
s->size = MAX;
s->length = 0;
}
void Push(stack *s, int k)
{
s->data[s->top++] = k;
s->length++;
}
void Pop(stack *s)
{
s->top--;
s->length--;
}
int Gettop(stack *s)
{
return s->data[s->top - 1];
}
int Empty(stack *s)
{
if(s->top == s->base)
return 1;
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: