Codeforces Round #271 (Div. 2) B Worms 裸的二分查找
2014-10-08 08:35
501 查看
B. Worms
time limit per test
1 second
memory limit per test
256 megabytes
input
standard input
output
standard output
It is lunch time for Mole. His friend, Marmot, prepared him a nice game for lunch.
Marmot brought Mole n ordered piles of worms such that i-th
pile contains ai worms.
He labeled all these worms with consecutive integers: worms in first pile are labeled with numbers 1 to a1,
worms in second pile are labeled with numbers a1 + 1 to a1 + a2 and
so on. See the example for a better understanding.
Mole can't eat all the worms (Marmot brought a lot) and, as we all know, Mole is blind, so Marmot tells him the labels of the best juicy worms. Marmot will only give Mole a worm if Mole says correctly in which pile this worm is contained.
Poor Mole asks for your help. For all juicy worms said by Marmot, tell Mole the correct answers.
Input
The first line contains a single integer n (1 ≤ n ≤ 105),
the number of piles.
The second line contains n integers a1, a2, ..., an (1 ≤ ai ≤ 103, a1 + a2 + ... + an ≤ 106),
where ai is
the number of worms in the i-th pile.
The third line contains single integer m (1 ≤ m ≤ 105),
the number of juicy worms said by Marmot.
The fourth line contains m integers q1, q2, ..., qm (1 ≤ qi ≤ a1 + a2 + ... + an),
the labels of the juicy worms.
Output
Print m lines to the standard output. The i-th line
should contain an integer, representing the number of the pile where the worm labeled with the number qi is.
Sample test(s)
input
output
给n个数,其对应一个前缀数组,
再给m个查询,每个查询是一个数,求出该数所在前缀的下标
就是一个裸的二分查找,但是自从田田学长讲过我们的方法是错的以后
一直以来二分都有点不太清楚,所以这里要记录一下
先看代码:
可以看到与我们以前写的不一样的地方,就是
也就是,high和low是直接等于mid的,而最关键的还是第一句mid=(high+low+1)/2;
二分查找无分三种情况
(1)找到a[mid]=tofind;
(2)夹在某三个 a[n+1] a
a[n-1] 之间,分别是h,m,l ,接着就会出现在a[n+1] a
(l=m)或者是在 a
a[n-1](h=m)之间的情况,
这个时候因为要求所在前缀,直接取较大的那个就好了
总结一下,如果仅仅是判断某个数组内是否有某个数,那么可以用以前的这种写法:
而如果想要求解在哪个前缀中,则应该使用这个写法:
time limit per test
1 second
memory limit per test
256 megabytes
input
standard input
output
standard output
It is lunch time for Mole. His friend, Marmot, prepared him a nice game for lunch.
Marmot brought Mole n ordered piles of worms such that i-th
pile contains ai worms.
He labeled all these worms with consecutive integers: worms in first pile are labeled with numbers 1 to a1,
worms in second pile are labeled with numbers a1 + 1 to a1 + a2 and
so on. See the example for a better understanding.
Mole can't eat all the worms (Marmot brought a lot) and, as we all know, Mole is blind, so Marmot tells him the labels of the best juicy worms. Marmot will only give Mole a worm if Mole says correctly in which pile this worm is contained.
Poor Mole asks for your help. For all juicy worms said by Marmot, tell Mole the correct answers.
Input
The first line contains a single integer n (1 ≤ n ≤ 105),
the number of piles.
The second line contains n integers a1, a2, ..., an (1 ≤ ai ≤ 103, a1 + a2 + ... + an ≤ 106),
where ai is
the number of worms in the i-th pile.
The third line contains single integer m (1 ≤ m ≤ 105),
the number of juicy worms said by Marmot.
The fourth line contains m integers q1, q2, ..., qm (1 ≤ qi ≤ a1 + a2 + ... + an),
the labels of the juicy worms.
Output
Print m lines to the standard output. The i-th line
should contain an integer, representing the number of the pile where the worm labeled with the number qi is.
Sample test(s)
input
5 2 7 3 4 9 3 1 25 11
output
1 5 3
给n个数,其对应一个前缀数组,
再给m个查询,每个查询是一个数,求出该数所在前缀的下标
就是一个裸的二分查找,但是自从田田学长讲过我们的方法是错的以后
一直以来二分都有点不太清楚,所以这里要记录一下
先看代码:
#include <iostream> #include <string.h> #include <stdio.h> #include <stdlib.h> #include <math.h> #include <memory.h> #include <string> #include <vector> #include <list> #include <map> #include <queue> #include <stack> #include <bitset> #include <algorithm> #include <numeric> #include <functional> #define maxn 100005 using namespace std; int n; int m; int a[maxn]; int binsearch(int tofind) { int high=n,low=1; if(tofind<=a[1]) return 1; while(1){ int mid=(high+low+1)/2; if(high==low+1) return high; else if(a[mid]==tofind) return mid; else if(a[mid]>tofind){ high=mid; } else if(a[mid]<tofind){ low=mid; } } } int main() { cin>>n; for(int i=1;i<=n;i+=1){ cin>>a[i]; if(i>1) a[i]+=a[i-1]; } cin>>m; for(int j=0;j<m;j+=1){ int k; cin>>k; cout<<binsearch(k)<<endl; } return 0; }
可以看到与我们以前写的不一样的地方,就是
int mid=(high+low+1)/2;还有
if(high==low+1) return high;和
else if(a[mid]>tofind){ high=mid; } else if(a[mid]<tofind){ low=mid; }
也就是,high和low是直接等于mid的,而最关键的还是第一句mid=(high+low+1)/2;
二分查找无分三种情况
(1)找到a[mid]=tofind;
(2)夹在某三个 a[n+1] a
a[n-1] 之间,分别是h,m,l ,接着就会出现在a[n+1] a
(l=m)或者是在 a
a[n-1](h=m)之间的情况,
这个时候因为要求所在前缀,直接取较大的那个就好了
总结一下,如果仅仅是判断某个数组内是否有某个数,那么可以用以前的这种写法:
int binsearch(int tofind) { int high=n,low=1; if(tofind<=a[1]) return 1; while(1){ int mid=(high+low)/2; if(high==low) return -1; else if(a[mid]==tofind) return mid; else if(a[mid]>tofind){ high=mid-1; } else if(a[mid]<tofind){ low=mid+1; } } }
而如果想要求解在哪个前缀中,则应该使用这个写法:
int binsearch(int tofind) { int high=n,low=1; if(tofind<=a[1]) return 1; while(1){ int mid=(high+low+1)/2; if(high==low+1) return high; else if(a[mid]==tofind) return mid; else if(a[mid]>tofind){ high=mid; } else if(a[mid]<tofind){ low=mid; } } }
相关文章推荐
- 【Codeforces Round 271 (Div 2)B】【前缀和二分 or 暴力】Worms 每种类型多个个数第i个数什么类型
- Codeforces Round #417 (Div. 2) C. Sagheer and Nubian Market(二分查找)
- Codeforces Round #202 (Div. 1) A. Mafia二分查找,玩游戏
- Codeforces Round #271 (Div. 2)--B.Worms
- Codeforces Round #256 (Div. 2) D. Multiplication Table(二分查找)
- 【Codeforces Round 367 (Div 2) B】【二分查找】Interesting drink
- Educational Codeforces Round 2B. Queries about less or equal elements(二分查找)
- 【Educational Codeforces Round 2B】【map or 二分查找】Queries about less or equal elements b[]中的每个数比a[]中多少数大
- 【Codeforces Round 271 (Div 2)A】【水题】Keyboard 打字列偏移还原原始串
- Codeforces Round #350 (Div. 2) D Magic Powder (二分)
- Codeforces Round #299 (Div. 1) A. Tavas and Karafs(二分)
- Codeforces Round #394 (Div. 2) D. Dasha and Very Difficult Problem 贪心,二分
- codeforces round 309 div1 Nudist Beach 二分+搜索
- Codeforces Round #172 (Div. 2) B. Nearest Fraction 二分
- Codeforces Round #360 (Div. 2) 前三题题解【简单模拟+思维+二分图判定二分染色】
- Codeforces Round #384 (Div. 2)E(状压dp+二分,好题)
- 【Codeforces Round 339 (Div 2)D】【暴力 贪心 二分】Skills 最高技能人数乘cm+最低技能乘cf权值最大
- Codeforces #352 Div2 D Robin Hood(二分查找)
- Codeforces Round #379 (Div. 2) C. Anton and Making Potions 枚举+二分
- Codeforces Round #227 (Div. 2) E. George and Cards set内二分+树状数组