10.12 考试 第二题 乌鸦喝水题解

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了10.12 考试 第二题 乌鸦喝水题解相关的知识,希望对你有一定的参考价值。

问题 B: 乌鸦喝水

时间限制: 2 Sec  内存限制: 128 MB

题目描述

【题目背景】
    一只乌鸦在自娱自乐,它在面前放了n个有魔力的水缸,水缸里装有无限的水。
【题目描述】
    他准备从第1个水缸飞到第n个水缸,共m次。在飞过一个水缸的过程中,如果他能够得着水缸里的水,即水缸口到水面距离小于等于乌鸦能够得着的深度,那它就会喝水缸里的水。每喝一次水,所有水缸里的水位都会下降,第i个水缸里的水位会下降Ai,注意喝水是瞬间的,如果乌鸦刚好够得着,但喝完之后够不着,也视为喝到一次,水位也会相应的下降。

Input

共有3行。第一行有三个正整数n、m和x,用空格隔开。n表示水缸的数量,m表示乌鸦飞的次数,x表示乌鸦能够得着的深度。第二行,有n个用空格隔开的正整数,第i个数为第i个水缸中水缸口到水面的距离Wi。第三行,有n个用空格隔开的正整数,第i个为Ai。

Output

只有一行,这一行只有一个正整数,为这只乌鸦能喝到水的次数。

Sample Input

5 2 20
15 14 13 12 12
1 1 1 1 1

Sample Output

9
【数据范围】
100%的数据,0<n≤100000,0<m≤100000,0<x≤2000000000,0<Wi≤2000000000,0<Ai≤200。
  从数据来看真心不好想到正解,但从数据来看,真心水。一个链表能骗95分,然而我明明95,却担心T太多,毕竟理论连50分都拿不到。于是乎我瞎打了一个上去,把95分改成了50分,名副其实的250。
  老师发了正解,由于里面很多都没说明白,去网上找了对应的标程理解,看了半天也没看懂,最后惊喜的发现标程本身就是错的,严重鄙视这种不负责任的行为。
  无奈,想呵呵酵母菌学他的打法(在这里%一发,他是考试的时候直接A掉的)。
  我们先把所有可能能喝到的筛出来,剪一下枝,然后将他们按照可以喝的次数-下标+1存储,也就是他可以在前面的水都被喝掉情况下再被喝几次。我们每一轮都去扫线段树的最小值,然后将它与我们现在的ans比对,如果它比ans大,那么说明所有水缸都可以被再喝一次,不然我们就一次剃掉左边的最小值,然后检查,最后对于答案加上场上现在还有多少水缸。
  
技术分享
  1 #include <iostream>
  2 #include <cstdlib>
  3 #include <cstdio>
  4 #include <cstring>
  5 #include <queue>
  6 #include <algorithm>
  7 #include <cmath>
  8 #include <map>
  9 #define N 100005
 10 using namespace std;
 11 int n,m,zz;
 12 long long l,w[N],a[N],b[N];
 13 long long ans;
 14 struct no
 15 {
 16     int left,mid,right;
 17     long long lazy,mn;
 18 }node[N*4];
 19 void build(int left,int right,int x)
 20 {
 21     node[x].left=left,node[x].right=right;
 22     if(left==right)
 23     {
 24         node[x].mn=b[left]-left+1;
 25         return;
 26     }
 27     int mid=(left+right)>>1;
 28     node[x].mid=mid;
 29     build(left,mid,2*x);
 30     build(mid+1,right,2*x+1);
 31     node[x].mn=min(node[x*2].mn,node[2*x+1].mn);
 32 }
 33 void pushdown(int x)
 34 {
 35     if(node[x].lazy)
 36     {
 37         node[2*x].lazy+=node[x].lazy;
 38         node[2*x+1].lazy+=node[x].lazy;
 39         node[2*x].mn+=node[x].lazy;
 40         node[2*x+1].mn+=node[x].lazy;
 41         node[x].lazy=0;
 42     }
 43 }
 44 int js;
 45 int del(int x,int z)
 46 {
 47     if(node[x].left==node[x].right)
 48     {
 49         node[x].mn=0x7fffffff;
 50         js--;
 51         return node[x].left;
 52     }
 53     pushdown(x);
 54     int ans=0;
 55     if(node[x*2].mn<=z)
 56         ans=del(2*x,z);
 57     else ans=del(2*x+1,z);
 58     node[x].mn=min(node[2*x].mn,node[2*x+1].mn);
 59     return ans;
 60 }
 61 void add(int left,int right,int x,int z)
 62 {
 63     if(node[x].left==left&node[x].right==right)
 64     {
 65         node[x].lazy+=z;
 66         node[x].mn+=z;
 67         return;
 68     }
 69     pushdown(x);
 70     int mid=node[x].mid;
 71     if(left>mid)add(left,right,2*x+1,z);
 72     else if(right<=mid)add(left,right,2*x,z);
 73     else add(left,mid,2*x,z),add(mid+1,right,2*x+1,z);
 74     node[x].mn=min(node[2*x].mn,node[2*x+1].mn);
 75 }
 76 int main()
 77 {
 78     scanf("%d%d%lld",&n,&m,&l);
 79     for(int i=1;i<=n;i++)
 80         scanf("%lld",&w[i]);
 81     for(int i=1;i<=n;i++)
 82         scanf("%lld",&a[i]);
 83     for(int i=1;i<=n;i++)
 84     {
 85         if((l-w[i])/a[i]+1>0)
 86         {
 87             zz++;
 88             b[zz]=(l-w[i])/a[i]+1;
 89         }
 90     }
 91     build(1,zz,1);
 92     n=zz;
 93     long long ans=0;js=n;
 94     for(int i=1;i<=m;i++)
 95     {
 96         if(node[1].mn>ans)ans+=js;
 97         else
 98         {
 99             while(node[1].mn<=ans)
100             {
101                 int t=del(1,ans);
102                 add(t,n,1,1);
103             }
104             ans+=js;
105         }   
106     }
107     printf("%lld\n",ans);
108     return 0;
109 }
View Code

 







以上是关于10.12 考试 第二题 乌鸦喝水题解的主要内容,如果未能解决你的问题,请参考以下文章

bzoj3441乌鸦喝水

9.18考试 第二题Dinner题解

10.13 1.0考试 第二题 学数数 题解

等级考试专题五:CSP-J 2020复赛第二题题解(桶排序的应用)

乌鸦喝水之谜

乌鸦喝水之谜