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 }