1. 程式人生 > >【CodeForces - 270C】Magical Boxes (思維,進位制,有坑)

【CodeForces - 270C】Magical Boxes (思維,進位制,有坑)

題幹:

Emuskald is a well-known illusionist. One of his trademark tricks involves a set of magical boxes. The essence of the trick is in packing the boxes inside other boxes.

From the top view each magical box looks like a square with side length equal to 2k(k is an integer, k ≥ 0) units. A magical box v

 can be put inside a magical box u, if side length of v is strictly less than the side length of u. In particular, Emuskald can put 4 boxes of side length 2k - 1 into one box of side length 2k, or as in the following figure:

Emuskald is about to go on tour performing around the world, and needs to pack his magical boxes for the trip. He has decided that the best way to pack them would be inside another magical box, but magical boxes are quite expensive to make. Help him find the smallest magical box that can fit all his boxes.

Input

The first line of input contains an integer n (1 ≤ n ≤ 105), the number of different sizes of boxes Emuskald has. Each of following n lines contains two integers ki and ai (0 ≤ ki ≤ 109, 1 ≤ ai ≤ 109), which means that Emuskald has ai boxes with side length 2k

i. It is guaranteed that all of ki are distinct.

Output

Output a single integer p, such that the smallest magical box that can contain all of Emuskald’s boxes has side length 2p.

Examples

Input

2
0 3
1 5

Output

3

Input

1
0 4

Output

1

Input

2
1 10
2 2

Output

3

Note

Picture explanation. If we have 3 boxes with side length 2 and 5 boxes with side length 1, then we can put all these boxes inside a box with side length 4, for example, as shown in the picture.

In the second test case, we can put all four small boxes into a box with side length 2.

 

題目大意:(練習讀題)

已知一個盒子(2^k)可以套四個小盒子(不能套和自己一樣大的盒子!)

如果一個盒子的邊長大於另一個盒子,那麼這個盒子就能夠容納那另一個盒子 。

問用多大邊長的正方形盒子,能夠容納所有給出的盒子。(也就是,如果全程一個盒子,需要再來一個盒子!讀題!)

第一行給出總共盒子數n,下面n行,每行兩個整數,分別代表盒子的大小  和  該大小盒子的盒子數量。(其中第一個盒子是用2的冪次給出。)

解題報告:

  這題我好像做麻煩了,,本來想直接用陣列下標代表2的冪次來著,,數量1e9的話也就是說冪次也就幾百而已。。但是發現是冪次是2e9(也就是說這題全程在用冪次,跟具體數字完全無關了),,所以就不能直接用陣列了,,考慮用map離散化一波,,不算難寫但是還是有坑的,比如不能直接除以4,,因為不一定相鄰兩個大小的盒子一定是大小相差1的,,仔細理解下就能看出來。(其實看了標解後發現不需要存資料的,,直接on_process一波就ok了)

 

AC程式碼1:(直接on出結果的)

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<queue>
#include<map>
#include<vector>
#include<set>
#include<string>
#include<cmath>
#include<cstring>
#define ll long long
#define pb push_back
#define pm make_pair
#define fi first
#define se second
using namespace std;
const int MAX = 2e5 + 5;
map<ll,ll> mp;
int main()
{
	int n;
	ll ans = 0;
	ll num,tmp,k;
	cin>>n;
	for(int i = 1; i<=n; i++) {
		scanf("%lld%lld",&k,&num);
		if(num == 1) k++;
		while(num > 1) {
			tmp = num%4 == 0 ? num/4 : num/4+1;
			num = tmp;
			k++;
		}
		ans = max(ans,k);
	}
	printf("%lld\n",ans);
	return 0 ;
 }
/*
2
0 3
1 5

*/

AC程式碼2:(map處理的)

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<queue>
#include<map>
#include<vector>
#include<set>
#include<string>
#include<cmath>
#include<cstring>
#define ll long long
#define pb push_back
#define pm make_pair
#define fi first
#define se second
using namespace std;
const int MAX = 2e5 + 5;
map<ll,ll> mp;
int main()
{
	int n;
	ll tmp,num;
	ll ans = 0;
	cin>>n;

	for(int i = 1; i<=n; i++) {
		scanf("%lld",&tmp);
		scanf("%lld",&num);
		ans = max(ans,tmp);
		mp[tmp] += num;
	}	
	map<ll,ll> :: iterator it = mp.begin(),end=mp.end(),ii;
	--end;
	
	for(;it != end; ++it) {
		num = it->se;
		++it;
		ii=it;
		--it;
		ll pp = pow(4,ii->fi - it->fi);
		tmp = num%pp == 0 ? num/pp : num/pp + 1;
		++it;
		if(it->se < tmp) {
			it->se += (tmp - it->se); 
		}
		--it;
	}
	num = end->se;
	if(num == 1) {
		printf("%lld\n",ans+1);
		return 0 ;
	}
	while(num >= 4) {
		tmp = num%4 == 0 ? num/4 : num/4 + 1;
		num=tmp;
		ans++;
	}
	
	ll out = num == 1 ? ans : ans+1;
	if(out==0) out=1;
	printf("%lld\n",out);
	return 0 ;
 }

總結:  掌握那種tmp=的那種方式,,經常需要處理一波(記得那次那個記憶化dp的計算幾何題處理邊的時候就需要這樣來著、、)