[BZOJ 3441]乌鸦喝水

3441: 乌鸦喝水

Time Limit: 20 Sec  Memory Limit: 128 MB
Submit: 374  Solved: 148
[Submit][Status][Discuss]

Description

【题目背景】
    一只乌鸦在自娱自乐,它在面前放了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。

HINT

 

 2016.7.8重设时限,未重测!

 

Source

题解

首先计算出每个水缸里的水能喝几次, 然后推出一个结论: 水少的水缸如果喝了 $n$ 次, 则水比它多的水缸也至少喝了 $n$ 次.

继续推还可以推出: 如果某一轮从某个水缸一直到结尾还能喝 $k$ 次, 而且该还能喝的次数 $\geq k$ , 则水比该水缸多的水缸不会在本轮被喝完.

然后我们就可以把水缸按照还可以喝的次数升序排序, 树状数组维护查询某水缸到结尾还能喝几次, 贪心处理即可

参考代码

GitHub

  1 #include <cstdio>
  2 #include <cstring>
  3 #include <cstdlib>
  4 #include <iostream>
  5 #include <algorithm>
  6 
  7 const int MAXN=1e6+10;
  8 
  9 int n;
 10 int m;
 11 int x;
 12 int r;
 13 int ans;
 14 int cnt;
 15 int last;
 16 int c[MAXN];
 17 
 18 std::pair<int,int> a[MAXN];
 19 
 20 int Query(int);
 21 int LowBit(int);
 22 void Add(int,int);
 23 void Initialize();
 24 int BinarySearch(int);
 25 
 26 int main(){
 27     Initialize();
 28     for(int i=1;i<=cnt;i++){
 29         if(a[i].first<ans){
 30             Add(a[i].second,-1);
 31         }
 32         else{
 33             int tmp=Query(cnt)-Query(last);
 34             while(r<m&&ans+tmp<=a[i].first){
 35                 r++;
 36                 ans+=tmp;
 37                 last=0;
 38                 tmp=Query(cnt)-Query(last);
 39             }
 40             if(r>=m)
 41                 break;
 42             int pos=BinarySearch(a[i].first-ans);
 43             ans=a[i].first;
 44             last=pos;
 45             Add(a[i].second,-1);
 46         }
 47     }
 48     printf("%d\n",ans);
 49     return 0;
 50 }
 51 
 52 int BinarySearch(int x){
 53     int ans=last,l=last,r=cnt;
 54     while(l<=r){
 55         int mid=(l+r)>>1;
 56         if(Query(mid)-Query(last)<=x){
 57             ans=mid;
 58             l=mid+1;
 59         }
 60         else
 61             r=mid-1;
 62     }
 63     return ans;
 64 }
 65 
 66 void Initialize(){
 67     int tmp;
 68     scanf("%d%d%d",&n,&m,&x);
 69     for(int i=1;i<=n;i++){
 70         scanf("%d",&a[i].first);
 71         a[i].second=i;
 72     }
 73     for(int i=1;i<=n;i++){
 74         scanf("%d",&tmp);
 75         a[i].first=(x-a[i].first)/tmp+1;
 76     }
 77     for(int i=1;i<=n;i++){
 78         if(a[i].first!=0){
 79             a[++cnt]=a[i];
 80             Add(a[i].second,1);
 81         }
 82     }
 83     std::sort(a+1,a+1+cnt);
 84 }
 85 
 86 void Add(int i,int x){
 87     while(i<=n){
 88         c[i]+=x;
 89         i+=LowBit(i);
 90     }
 91 }
 92 
 93 int Query(int x){
 94     int ans=0;
 95     while(x>0){
 96         ans+=c[x];
 97         x-=LowBit(x);
 98     }
 99     return ans;
100 }
101 
102 inline int LowBit(int x){
103     return x&-x;
104 }
Backup

 

 

posted @ 2017-10-12 21:46  rvalue  阅读(539)  评论(0编辑  收藏  举报