BZOJ 1510: Kra-The Disks

Johnny 在生日时收到了一件特殊的礼物,这件礼物由一个奇形怪状的管子和一些盘子组成. 这个管子是由许多不同直径的圆筒(直径也可以相同) 同轴连接而成. 这个管子的底部是封闭的,顶部是打开的. 下图是由直径为: 5cm, 6cm, 4cm, 3cm, 6cm, 2cm and 3cm 的圆筒组成的管子. 
这里写图片描述 
每个圆筒的高度都是相等的, 玩具中所带的盘子也是一些高度和它们相同的圆筒,直径有大有小. Johnny 发明了一种游戏,把盘子从管子顶部一个接一个的扔下去,他想知道最后这些盘子落在了哪,假设盘子落下过程中圆心和管子的轴一直保持一致,比如说我们丢下去三个盘子: 3cm, 2cm and 5cm, 下图展示了最终它们的停止位置: 
这里写图片描述 

如图可以知道,盘子掉下去以后,要么被某个圆筒卡住,要么就是因为掉在了以前的一个盘子上而停住. Johnny 想知道他最后扔下去的那个盘子掉在了哪个位置,你来帮他把. 
Input

第一行两个整数 n 和 m ( 1<= n, m<= 300 000) 表示水管包含的圆筒数以及盘子总数. 第二行给出 n 个整数 r1, r2,…,rn ( 1 <=ri<= 1 000 000 000 for 1<= i<= n) 表示水管从上到下所有圆筒的直径. 第三行给出m 个整数k1, k2,…, km ( 1<= kj<= 1 000 000 000 for 1<= j<= m) 分别表示Johnny 依次扔下去的盘子直径. 
Output

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

7 3

5 6 4 3 6 2 3

3 2 5

Sample Output

2

题解:

单调队列

显然,当i>j,r[i]>r[j]时r[i]可以视为r[j],对题目不会有影响

样例就变成了5 5 4 3 3 2 2

直接单调队列就行了,复杂度O(n+m)

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 using namespace std;
 6 int n,m,r[300001],tail;
 7 int main()
 8 {int i,j,x;
 9 //freopen("kra.in","r",stdin);
10 //freopen("kra.out","w",stdout);
11     cin>>n>>m;
12      for (i=1;i<=n;i++)
13      {
14          scanf("%d",&r[i]);
15      }
16      r[0]=2e9;
17      for (i=1;i<=n;i++)
18      if (r[i]>r[i-1]) r[i]=r[i-1];
19      tail=n;
20       for (i=1;i<=m;i++)
21       {
22           scanf("%d",&x);
23           if (tail==0)
24           {
25               cout<<0<<endl;
26               return 0;
27         }
28            while (r[tail]<x) 
29            {
30                if (tail==1) 
31                {
32                    cout<<0<<endl;
33                    return 0;
34             }
35             tail--;
36            }
37            tail--;
38       }
39     cout<<tail+1<<endl;
40 }

 

posted @ 2017-07-21 12:27  Z-Y-Y-S  阅读(293)  评论(0编辑  收藏  举报