洛谷 P3434 [POI2006]KRA-The Disks 贪心

题面

题目链接

P3434 [POI2006]KRA-The Disks

题目描述

一个框,告诉你每一层的宽度。

向下丢给定宽度的木块。

木块会停在卡住他的那一层之上,异或是已经存在的木块之上。

询问丢的最后一个木块停在第几层。

输入输出格式

输入格式

第一行两个整数 $ n $ 和 $ m (1 leq n, mleq 300 000) $ 表示水管包含的圆筒数以及盘子总数. 第二行给出 $ n $ 个整数 $ r_1, r_2,...,r_n ( 1 leq r_i leq 1 000 000 000) $ 表示水管从上到下所有圆筒的直径. 第三行给出 $ m $ 个整数 $ k_1, k_2,..., k_m ( 1leq k_j leq 1 000 000 000) $ 分别表示Johnny 依次扔下去的盘子直径

输出格式

一个整数输出最后一个盘子掉在了哪一层,如果盘子不能扔进水管,那么打印0

输入输出样例

输出样例

7 3
5 6 4 3 6 2 3
3 2 5

输出样例

2

说明

【时空限制】

1000ms,128MB

思路

首先要明确一个事实。如果上面一层比下面一层窄,那么实际上下层可用的面积和上一层是一样大的。所以像这样读入是肯定没有问题的。

scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
{
    scanf("%d",&h[i]);
    if(i!=1) h[i]=min(h[i],h[i-1]);
}

再模拟这个过程。第一个盘子肯定停留在从上往下最后宽度比他大的那一层,然后这个盘子的下面部分都没有用了。所以从后往前扫一遍就行了

AC代码

#include<bits/stdc++.h>
const int maxn=300010;
using namespace std;

int n,m;
int h[maxn];
int np;

int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&h[i]);
        if(i!=1) h[i]=min(h[i],h[i-1]);
    }
    np=n+1;
    for(int i=1,tmp;i<=m;i++)
    {
        scanf("%d",&tmp);
        np--; ///这里要注意。np是上一个盘子的位置,这一个盘子不能掉在np的位置了。
        while(h[np]<tmp && np>0) np--;
        if(np==0) break;
    }
    printf("%d",np);
    return 0;
}
原文地址:https://www.cnblogs.com/Mercury04/p/9813003.html