CF 2018.09.02 22:35 题解(补)

比赛题目链接:http://codeforces.com/contest/1037

A. Packets

You have nn coins, each of the same value of 11.

Distribute them into packets such that any amount xx (1≤x≤n1≤x≤n) can be formed using some (possibly one or all) number of these packets.

Each packet may only be used entirely or not used at all. No packet may be used more than once in the formation of the single xx, however it may be reused for the formation of other xx's.

Find the minimum number of packets in such a distribution.

Input

The only line contains a single integer nn (1≤n≤1091≤n≤109) — the number of coins you have.

Output

Output a single integer — the minimum possible number of packets, satisfying the condition above.

Examples

input

6

output

3

input

2

output

2

Note

In the first example, three packets with 11, 22 and 33 coins can be made to get any amount xx (1≤x≤61≤x≤6).

  • To get 11 use the packet with 11 coin.
  • To get 22 use the packet with 22 coins.
  • To get 33 use the packet with 33 coins.
  • To get 44 use packets with 11 and 33 coins.
  • To get 55 use packets with 22 and 33 coins
  • To get 66 use all packets.

In the second example, two packets with 11 and 11 coins can be made to get any amount xx (1≤x≤21≤x≤2).

大意就是将一个数n拆成x个数,使得可从这x个数中取一些数构成1~n的任何数,求x的最小值。

思路:类似数状数组那种拆分,使用“&”运算符。

我的代码:

#include
using namespace std;
int main() {
	int a,ans=0;
	scanf("%d",&a);
	while(1) {
		if(a==(a&(-a))) break;
		else a-=(a&(-a));
	}
	while(1) {
		if(a%2==0) {
			a/=2;
			ans++;
		}
		else break;
	}
	printf("%d",ans+1);
}

 

B. Reach Median

You are given an array aa of nn integers and an integer ss. It is guaranteed that nn is odd.

In one operation you can either increase or decrease any single element by one. Calculate the minimum number of operations required to make the median of the array being equal to ss.

The median of the array with odd length is the value of the element which is located on the middle position after the array is sorted. For example, the median of the array 6,5,86,5,8 is equal to 66, since if we sort this array we will get 5,6,85,6,8, and 66 is located on the middle position.

Input

The first line contains two integers nn and ss (1≤n≤2⋅105−11≤n≤2⋅105−1, 1≤s≤1091≤s≤109) — the length of the array and the required value of median.

The second line contains nn integers a1,a2,…,ana1,a2,…,an (1≤ai≤1091≤ai≤109) — the elements of the array aa.

It is guaranteed that nn is odd.

Output

In a single line output the minimum number of operations to make the median being equal to ss.

Examples

input

3 8
6 5 8

output

2

input

7 20
21 15 12 11 20 19 12

output

6

Note

In the first sample, 66 can be increased twice. The array will transform to 8,5,88,5,8, which becomes 5,8,85,8,8 after sorting, hence the median is equal to 88.

In the second sample, 1919 can be increased once and 1515 can be increased five times. The array will become equal to 21,20,12,11,20,20,1221,20,12,11,20,20,12. If we sort this array we get 11,12,12,20,20,20,2111,12,12,20,20,20,21, this way the median is 2020.

题意:给一个n个数的序列和整数s,现在要对序列中的数+1或-1,使得该序列的中位数为s,问这样的+1或-1操作最少要多少次。

思路:排序,从它的中位数开始向左(或向右)把其中一侧大于(或小于)s的数变为s,并记录变动值,累加即为答案。

注意点:数据过大,要用long long int输出。

代码:

#include
#include
#define ll long long
using namespace std;
ll int a[200000],ans;
int main() {
	int n,s,j;
	scanf("%d%d",&n,&s);
	for(int i=0;i=a[(n-1)/2]) {
		while(1) {
			if(a[j]>=s) break;
			ans+=(s-a[j]);
			j++;
			if(j==n) break;
		}
	}
	else {
		while(1) {
			if(a[j]<=s) break;
			ans+=(a[j]-s);
			j--;
			if(j==-1) break;
		}
	}
	printf("%lld",ans);
} 

 

C. Equalize

You are given two binary strings aa and bb of the same length. You can perform the following two operations on the string aa:

  • Swap any two bits at indices ii and jj respectively (1≤i,j≤n1≤i,j≤n), the cost of this operation is |i−j||i−j|, that is, the absolute difference between ii and jj.
  • Select any arbitrary index ii (1≤i≤n1≤i≤n) and flip (change 00 to 11 or 11 to 00) the bit at this index. The cost of this operation is 11.

Find the minimum cost to make the string aa equal to bb. It is not allowed to modify string bb.

Input

The first line contains a single integer nn (1≤n≤1061≤n≤106) — the length of the strings aa and bb.

The second and third lines contain strings aa and bb respectively.

Both strings aa and bb have length nn and contain only '0' and '1'.

Output

Output the minimum cost to make the string aa equal to bb.

Examples

input

3
100
001

output

2

input

4
0101
0011

output

1

Note

In the first example, one of the optimal solutions is to flip index 11 and index 33, the string aa changes in the following way: "100" →→ "000" →→"001". The cost is 1+1=21+1=2.

The other optimal solution is to swap bits and indices 11 and 33, the string aa changes then "100" →→ "001", the cost is also |1−3|=2|1−3|=2.

In the second example, the optimal solution is to swap bits at indices 22 and 33, the string aa changes as "0101" →→ "0011". The cost is |2−3|=1|2−3|=1.

题意:求把两个字符串变成相同需要的最少价值,其中改变一个元素价值为1,交换两个元素的价值为两元素的位置之差。

思路:又是签到题。。基本常识思路,从头开始改即可,先看是否能交换,不能的话再单个修改。

注意:二进制数要用字符数组,不要把换行符读进去。

代码:

#include
#include
using namespace std;
char a[1000000],b[1000000];    //超过1e6时要用全局变量
int main() {
	int n,ans=0;
	scanf("%d",&n);
	scanf("%c",&a[0]);
	if(a[0]=='\n') scanf("%c",&a[0]);    //排除换行符干扰
	for(int i=1;i

 

D. Valid BFS?

The BFS algorithm is defined as follows.

  1. Consider an undirected graph with vertices numbered from 11 to nn. Initialize qq as a new queue containing only vertex 11, mark the vertex 11 as used.
  2. Extract a vertex vv from the head of the queue qq.
  3. Print the index of vertex vv.
  4. Iterate in arbitrary order through all such vertices uu that uu is a neighbor of vv and is not marked yet as used. Mark the vertex uu as used and insert it into the tail of the queue qq.
  5. If the queue is not empty, continue from step 2.
  6. Otherwise finish.

Since the order of choosing neighbors of each vertex can vary, it turns out that there may be multiple sequences which BFS can print.

In this problem you need to check whether a given sequence corresponds to some valid BFS traversal of the given tree starting from vertex 11. The tree is an undirected graph, such that there is exactly one simple path between any two vertices.

Input

The first line contains a single integer nn (1≤n≤2⋅1051≤n≤2⋅105) which denotes the number of nodes in the tree.

The following n−1n−1 lines describe the edges of the tree. Each of them contains two integers xx and yy (1≤x,y≤n1≤x,y≤n) — the endpoints of the corresponding edge of the tree. It is guaranteed that the given graph is a tree.

The last line contains nn distinct integers a1,a2,…,ana1,a2,…,an (1≤ai≤n1≤ai≤n) — the sequence to check.

Output

Print "Yes" (quotes for clarity) if the sequence corresponds to some valid BFS traversal of the given tree and "No" (quotes for clarity) otherwise.

You can print each letter in any case (upper or lower).

Examples

input

4
1 2
1 3
2 4
1 2 3 4

output

Yes

input

4
1 2
1 3
2 4
1 2 4 3

output

No

Note

Both sample tests have the same tree in them.

In this tree, there are two valid BFS orderings:

  • 1,2,3,41,2,3,4,
  • 1,3,2,41,3,2,4.

The ordering 1,2,4,31,2,4,3 doesn't correspond to any valid BFS order.

题意:分析一下BFS(广度优先)算法的顺序,并判断题目给的顺序是否可能存在

注意:队列是先进先出!遇到莫名其妙的结果就疯狂加printf语句排除错误找到关键,花费了我巨大的时间。。。以后要理清思路才行,注释就是debug的痕迹,花费两个多小时,WA近10次最终能靠自己写出来真的十分感动,但是代码写得太难懂了,这样命名不好。

代码:

#include 
#include 
#include 
using namespace std;
vector  a[200005];
queue  q,dui,dui1;
int t[200005],s[200005],fu[200005],t1[200005]; 
int main() {
	int n,x,y,f,si,ans=1,j,st;
	for(int i=0;i<200005;i++) t[i]=1;	//标记是否已经检查过 
	scanf("%d",&n);
	for(int i=1;i0;si--) {
			if(t[a[f][si-1]]) fu[a[f][si-1]]=f;
			if(t[a[f][si-1]]) q.push(a[f][si-1]);
			else continue;
			s[a[f][si-1]]=s[f]+1;
			t[a[f][si-1]]=0;
		}
	}
	//for(int i=1;i<=n;i++) printf("%d->%d\n",i,s[i]);
    for(int i=1;i<=n;i++) {
    	scanf("%d",&t[i]);
    	//if((i==2&&t[i]==5)||(i==5&&t[i]==6)) ans=0;
    	t1[i]=s[t[i]];
	}
	for(int i=1;it1[i+1]) {
			ans=0;
			break;
		}
	}
	//if(n==200000) ans=1;
	if(ans==0) printf("No");
	else {
		//printf("哈"); 
		j=2;
		for(int i=2;ii) break;
				dui.push(t[j]);
				//printf("放进队列:t[%d]=%d\n",j,t[j]);
				j++;
			}
			st=j;
			while(1) {
				//printf("第二个循环:"); 
				if(fu[t[st]]!=dui.front()) {
					//printf("删除%d",dui.front());
					dui.pop();
					//printf("现尺寸:%d\n",dui.size());
					st--;
				}
				st++;
				if(t1[j]!=t1[st]||dui.size()==0||st>n) break;
			}
			if(dui.size()==0) {
				ans=0;
				break;
			}
			while(!dui.empty()) dui.pop();
		}
		//printf("\n答案:ans=%d\n",ans);
		if(ans==0) printf("No");
		else printf("Yes");
	}
	//for(int i=1;i<=n;i++) printf("%d->%d\n",i,fu[i]);
}

 

你可能感兴趣的:(算法)