1. 程式人生 > >10.12 考試 第二題 烏鴉喝水題解

10.12 考試 第二題 烏鴉喝水題解

none build 鄙視 blog 內存 數量 tdi gree alt

問題 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 考試 第二題 烏鴉喝水題解