codeforces #354

本文解析了Codeforces竞赛中的三道题目,包括排列最远距离问题、玻璃金字塔填充问题及字符串最大相同子串长度问题,提供了多种算法解决方案。

唉,打得不好。。。第一题错了一次就算了,第二题根本就想错了!照着错误的方向想了半天,每次都错在第4组数据。。回头一想,觉得简单,再一打,错到了第28组数据,后来陆陆续续错到了第36组,第1组。。第83组。。。。。。。好吧,掉分我也认了。。。反正我菜。。

A. Nicholas and Permutation
time limit per test
1 second
memory limit per test
256 megabytes
input
standard input
output
standard output

Nicholas has an array a that contains n distinct integers from 1 to n. In other words, Nicholas has a permutation of size n.

Nicholas want the minimum element (integer 1) and the maximum element (integer n) to be as far as possible from each other. He wants to perform exactly one swap in order to maximize the distance between the minimum and the maximum elements. The distance between two elements is considered to be equal to the absolute difference between their positions.

Input

The first line of the input contains a single integer n (2 ≤ n ≤ 100) — the size of the permutation.

The second line of the input contains n distinct integers a1, a2, ..., an (1 ≤ ai ≤ n), where ai is equal to the element at the i-th position.

Output

Print a single integer — the maximum possible distance between the minimum and the maximum elements Nicholas can achieve by performing exactly one swap.

Examples
input
5
4 5 1 3 2
output
3
input
7
1 6 5 3 4 7 2
output
6
input
6
6 5 4 3 2 1
output
5
Note

In the first sample, one may obtain the optimal answer by swapping elements 1 and 2.

In the second sample, the minimum and the maximum elements will be located in the opposite ends of the array if we swap 7 and 2.

In the third sample, the distance between the minimum and the maximum elements is already maximum possible, so we just perform some unnecessary swap, for example, one can swap 5 and 2.


没什么好说的,我一开始单纯的以为只要固定最大的移最小的或者是固定最小的移最大的就行。。结果错了。。仔细一想。。唉

/*
 * main.cpp
 *
 *  Created on: 2016年5月25日
 *      Author: Triose
 */
#include<stdio.h>
#include<iostream>
#include<string>
#include<string.h>
#include<algorithm>
#include<vector>
#include<queue>
#include<stack>
#include<iterator>
#include<math.h>
#include<stdlib.h>
#include<map>
#include<set>
using namespace std;
//#define ONLINE_JUDGE
#define eps 1e-8
#define INF 0x7fffffff
#define inf 0x3f3f3f3f
#define rep(i,a) for(int (i)=0; i<(a);(i)++)
#define mem(a,b) (memset((a),b,sizeof(a)))
#define sf(a) scanf("%d",&a)
#define sfI(a) scanf("%I64d",&a)
#define sfd(a,b) scanf("%d%d",&a,&b)
#define sft(a,b,c) scanf("%d%d%d",&a,&b,&c)
#define sfs(a) scanf("%s",a)
#define pf(a) printf("%d\n",a)
#define pfd(a,b) printf("%d %d\n",a,b)
#define pfs(a) printf("%s\n",a)
#define pfI(a) printf("%I64d\n",a)
#define enter putchar(10)
#define LL __int64
const double PI = acos(-1.0);
const double E = exp(1.0);
template<class T> T gcd(T a, T b) { return b ? gcd(b, a%b) : a; }
template<class T> T lcm(T a, T b) { return a / gcd(a, b)*b; }
template<class T> inline T Min(T a, T b) { return a<b ? a : b; }
template<class T> inline T Max(T a, T b) { return a>b ? a : b; }
int n, m;
#define N 110
int maxpos, minpos;
int main() {
#ifndef ONLINE_JUDGE
	freopen("in.txt","r",stdin);
//	freopen("Out.txt", "w", stdout);
#endif
	while(~sf(n)) {
		int tmp;
		rep(i, n) {
			sf(tmp);
			if(tmp == n) maxpos = i + 1;
			if(tmp == 1) minpos = i + 1;
		}
		pf(Max(n - Min(maxpos, minpos), Max(maxpos, minpos) - 1));
	}
	return 0;
}


第二题。。我真的很少看见有2400+的人过的dp了。。

B. Pyramid of Glasses
time limit per test
1 second
memory limit per test
256 megabytes
input
standard input
output
standard output

Mary has just graduated from one well-known University and is now attending celebration party. Students like to dream of a beautiful life, so they used champagne glasses to construct a small pyramid. The height of the pyramid is n. The top level consists of only 1 glass, that stands on 2 glasses on the second level (counting from the top), then 3 glasses on the third level and so on.The bottom level consists of n glasses.

Vlad has seen in the movies many times how the champagne beautifully flows from top levels to bottom ones, filling all the glasses simultaneously. So he took a bottle and started to pour it in the glass located at the top of the pyramid.

Each second, Vlad pours to the top glass the amount of champagne equal to the size of exactly one glass. If the glass is already full, but there is some champagne flowing in it, then it pours over the edge of the glass and is equally distributed over two glasses standing under. If the overflowed glass is at the bottom level, then the champagne pours on the table. For the purpose of this problem we consider that champagne is distributed among pyramid glasses immediately. Vlad is interested in the number of completely full glasses if he stops pouring champagne in t seconds.

Pictures below illustrate the pyramid consisting of three levels.

Input

The only line of the input contains two integers n and t (1 ≤ n ≤ 10, 0 ≤ t ≤ 10 000) — the height of the pyramid and the number of seconds Vlad will be pouring champagne from the bottle.

Output

Print the single integer — the number of completely full glasses after t seconds.

Examples
input
3 5
output
4
input
4 8
output
6
Note

In the first sample, the glasses full after 5 seconds are: the top glass, both glasses on the second level and the middle glass at the bottom level. Left and right glasses of the bottom level will be half-empty.



做的时候我居然没有想到前后问题的相关性!只是想着只要有一单位体积的水就算是满了,结果错的不行。。。

题意一目了然,就是说有n层杯子,第i层有i个杯子,从第一层倒水,每隔一秒钟倒下一体积的水,而杯子的容量正好是一体积。问你,现在有n层杯子,倒t秒钟水,能倒满几个杯子?

这么想: 

1、 t 秒钟水,即是t体积水

2、 题目数据范围不大,你可以用一个dp[N][N]数组存下每个杯子的状态,即杯中有多少水

3、 状态转移方程:

    if ( dp[i][j] >= 1 ) { //你要把水流到下面的杯子里去,首先自己要满了是不是?

dp[ i + 1 ][ j ]  += (dp[ i ][ j] - 1) / 2;//[i + 1][j] 是左边的杯子,分一半(减去一之后的一半!)

                 dp[i + 1][j + 1] += (dp[i][j] - 1) / 2;//[i + 1][j + 1] 是右边的杯子,分一半

     }

4、 统计哪些杯子大于等于1就行了。。

/*************************************************************************
    > File Name: B.cpp
    > Author: Triose
    > Mail: Triose@163.com 
    > Created Time: 2016/5/26 星期四 上午 3:07:41
 ************************************************************************/
#include<bits/stdc++.h>
using namespace std;
#define N 15
const double esp = 1e-5;
double tmp[N][N];
int n, t;
int main() {
#ifndef ONLINE_JUDGE
	freopen("in.txt", "r", stdin);
#endif
	while(cin >> n >> t) {
		int tot = 0;
		memset(tmp, 0, sizeof(tmp));
		tmp[0][0] = t * 1.0;
		for(int i = 0; i < n - 1; i++) {
			for(int j = 0; j <= i; j++) {
				tmp[i + 1][j] += ((tmp[i][j] - 1 > 0 ? tmp[i][j] - 1 : 0)/ 2);
				tmp[i + 1][j + 1] += ((tmp[i][j] - 1 > 0 ? tmp[i][j] - 1 : 0)/ 2);
			}
		}
		for(int i = 0; i < n; i++) {
			for(int j = 0; j <= i; j++) {
				if(tmp[i][j] >= 1) tot++;
			}
		}
		/*
		for(int i = 0; i < n; i++) {
			for(int j = 0; j <= i; j++) {
				cout << tmp[i][j] << " ";
			}
			cout << endl;
		}
		*/
		cout << tot << endl;
	}
	return 0;
}
注释的那段是调试代码。


第三题搞定了。。。我想了三种做法,O(n ^ 2) 的, O(n logn)的, 和一个O(n)的。。准备一个一个试。


C. Vasya and String
time limit per test
1 second
memory limit per test
256 megabytes
input
standard input
output
standard output

High school student Vasya got a string of length n as a birthday present. This string consists of letters 'a' and 'b' only. Vasya denotesbeauty of the string as the maximum length of a substring (consecutive subsequence) consisting of equal letters.

Vasya can change no more than k characters of the original string. What is the maximum beauty of the string he can achieve?

Input

The first line of the input contains two integers n and k (1 ≤ n ≤ 100 000, 0 ≤ k ≤ n) — the length of the string and the maximum number of characters to change.

The second line contains the string, consisting of letters 'a' and 'b' only.

Output

Print the only integer — the maximum beauty of the string Vasya can achieve by changing no more than k characters.

Examples
input
4 2
abba
output
4
input
8 1
aabaabaa
output
5
Note

In the first sample, Vasya can obtain both strings "aaaa" and "bbbb".

In the second sample, the optimal answer is obtained with the string "aaaaabaa" or with the string "aabaaaaa".


题目的数据范围是 10 ^ 5, 我试了试O(n ^ 2),结果TLE在了第10组数据。

这是代码:

/*************************************************************************
    > File Name: C.cpp
    > Author: Triose
    > Mail: Triose@163.com 
    > Created Time: 2016/5/28 星期六 下午 5:15:12
 ************************************************************************/
#include<stdio.h>
#include<string.h>
#define N 100010
char str[N];
int a[N], b[N];
int n,m;
int max(int u, int v) {
	return u > v ? u : v;
}
int main() {
#ifndef ONLINE_JUDGE
	freopen("in.txt", "r", stdin);
#endif
	while(~scanf("%d%d",&n,&m)) {
		memset(a, 0, sizeof(a));
		memset(b, 0, sizeof(b));
		scanf("%s", str + 1);
		int lena = 0;
		int lenb = 0;
		for(int i = 0; i <= n; i++) {
			a[i] = (str[i] == 'a' ? a[i - 1] + 1 : a[i - 1]);
			b[i] = (str[i] == 'b' ? b[i - 1] + 1 : b[i - 1]);
		}
		/*
		for(int i = 0; i <= n; i++) {
			printf("%d ", a[i]);
		}
		putchar(10);
		for(int i = 0; i <= n; i++) {
			printf("%d ", b[i]);
		}
		putchar(10);
		*/
		for(int i = 1; i <= n; i++) {
			for(int j = 1; j <= n; j++) {
				if(b[j] - b[i - 1] <= m) lena = max(lena, j - i + 1);
				if(a[j] - a[i - 1] <= m) lenb = max(lenb, j - i + 1);
			}
		}
		printf("%d\n", max(lena, lenb));

	}
	return 0;
}
如果这都能过,估计这题的过题数就到4000+了。。。

既然O(n ^ 2)不行, 那试试O(n logn)把,div2的题目估计就只要优化成这样了吧。。。

前缀和 + 二分(很巧妙的想法,虽然前缀和我会,二分我也会,不过从来没有想过前缀和是有序的,有序就可以二分查找。。。)  让我很疑惑的是,为什么这道题会有dp的标签。。。可能是 suma[i] = suma[i - 1] + (str[i] == 'a');把?。。。。。

/*************************************************************************
    > File Name: C.cpp
    > Author: Triose
    > Mail: Triose@163.com 
    > Created Time: 2016/5/28 星期六 下午 5:15:12
 ************************************************************************/
#include<stdio.h>
#include<string.h>
#define N 100010
char str[N];
int a[N], b[N];
int n,m;
int max(int u, int v) {
	return u > v ? u : v;
}
int binary(int s, int e, int flag) {
	int low = s + m, high = e;
	if(low > n) low = n;
	int *tmp = (flag ? a : b);
	while(low < high) {
		int mid = (low + high) >> 1;
		if(tmp[mid] - tmp[s - 1] <= m) {
			if(tmp[mid + 1] - tmp[s - 1] > m) {
				return mid - s + 1;
			}
			low = mid + 1;
		}
		else {
			if(tmp[mid - 1] - tmp[s - 1] == m) {
				return mid - s;
			}
			high = mid - 1;
		}
	}
	return low - s + 1;
}
int main() {
#ifndef ONLINE_JUDGE
	freopen("in.txt", "r", stdin);
#endif
	while(~scanf("%d%d",&n,&m)) {
		memset(a, 0, sizeof(a));
		memset(b, 0, sizeof(b));
		scanf("%s", str + 1);
		int lena = 0;
		int lenb = 0;
		for(int i = 0; i <= n; i++) {
			a[i] = (str[i] == 'a' ? a[i - 1] + 1 : a[i - 1]);
			b[i] = (str[i] == 'b' ? b[i - 1] + 1 : b[i - 1]);
		}
		for(int i = 1; i <= n; i++) {
			lena = max(lena, binary(i, n, 0));
			lenb = max(lenb, binary(i, n, 1));
		}
		printf("%d\n", max(lena, lenb));

	}
	return 0;
}

这两题我都没用IDE,感觉虽然Windows下的gvim虽然有点蹩脚,不过还是勉强能用的。。。



后来我又想了想,O(n)没想出来。。。不知道是否存在。。。要确定最长的左右端点,肯定得求左端点和求右端点,再优化也就只能优化到nlogn了吧?

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值