第四次codeforces竞技结束 #FF(#255) Div 2

这次第一次吃到了Pretest Passed但是Final WA的情况……哭瞎简直……怪我写快了没想的很多……

A. DZY Loves Hash

time limit per test
1 second
memory limit per test
256 megabytes
input
standard input
output
standard output

DZY has a hash table with p buckets, numbered from 0 to p - 1. He wants to insert n numbers, in the order they are given, into the hash table. For the i-th number xi, DZY will put it into the bucket numbered h(xi), where h(x) is the hash function. In this problem we will assume, that h(x) = x mod p. Operation a mod b denotes taking a remainder after division a by b.

However, each bucket can contain no more than one element. If DZY wants to insert an number into a bucket which is already filled, we say a "conflict" happens. Suppose the first conflict happens right after the i-th insertion, you should output i. If no conflict happens, just output -1.

Input

The first line contains two integers, p and n (2 ≤ p, n ≤ 300). Then n lines follow. The i-th of them contains an integer xi (0 ≤ xi ≤ 109).

Output

Output a single integer — the answer to the problem.

Sample test(s)
input
10 5
0
21
53
41
53
output
4
input
5 5
0
1
2
3
4
output
-1

这个说的是hash表,就是说问第一个哈希冲突部分的index(详情请见数据结构课本)。

Code:

#include <cmath>   
#include <vector>  
#include <cctype>  
#include <cstdio>  
#include <string>  
#include <cstdlib>  
#include <cstring>  
#include <iostream>  
#include <algorithm>  
using namespace std;
int p,n;
int hash[301];

int geth(int x)
{
	return x%p;
}

int main()
{
	int flag=0;
	memset(hash,0,sizeof hash);
	scanf("%d%d",&p,&n);
	for(int i=1;i<=n;i++)
	{
		int tmp;
		scanf("%d",&tmp);
		if(hash[geth(tmp)]==0)hash[geth(tmp)]=1;
		else if(!flag)
						{
							flag=i;
							break;
						}
	}
	if(!flag)printf("-1");
	else printf("%d",flag);
	
	return 0;
}

B. DZY Loves Strings

time limit per test
1 second
memory limit per test
256 megabytes
input
standard input
output
standard output

DZY loves collecting special strings which only contain lowercase letters. For each lowercase letter c DZY knows its value wc. For each special string s = s1s2... s|s| (|s| is the length of the string) he represents its value with a function f(s), where

Now DZY has a string s. He wants to insert k lowercase letters into this string in order to get the largest possible value of the resulting string. Can you help him calculate the largest possible value he could get?

Input

The first line contains a single string s (1 ≤ |s| ≤ 103).

The second line contains a single integer k (0 ≤ k ≤ 103).

The third line contains twenty-six integers from wa to wz. Each such number is non-negative and doesn't exceed 1000.

Output

Print a single integer — the largest possible value of the resulting string DZY could get.

Sample test(s)
input
abc
3
1 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
output
41
Note

In the test sample DZY can obtain "abcbbc", value = 1·1 + 2·2 + 3·2 + 4·2 + 5·2 + 6·2 = 41.


这个的意思是字母表26个字母各代表着一个值,现在有一个字符串s了,问我们加上k个字母之后,这个式子的最大值是多少呢?

那么如果是一个字符串的需求值最大的话,那肯定是全都是值最大的字母组成的字符串了,但是其中有几个字母是给定的,放在哪里好呢?难不成要枚举嘛?怎么可能啦……因为这个式子是越靠后的越有效,所以不管原来的字符串是什么,全都扔到最前面就行了呗~

所以就直接把原先字符串的值算出来,然后加上k个最大值乘以位权即可。

Code:

#include <cmath>   
#include <vector>  
#include <cctype>  
#include <cstdio>  
#include <string>  
#include <cstdlib>  
#include <cstring>  
#include <iostream>  
#include <algorithm>  
using namespace std;
typedef __int64 ll;

string 	s;
int 	k,ans;
int 	w[27]; //0forMAX ,1~26


void init()
{
	
	for(int i=1;i<=26;i++)
	{
		scanf("%d",&w[i]);
		if(w[i]>=w[0])w[0]=w[i];
	}
}

void solve()
{
	int temp=0;
	temp += s.length()*2+k+1;// div2 & mulw[0]
	temp *= k;
	temp /= 2;
	temp *= w[0];
	//cout<<s.length()<<endl;
	//cout<<ans<<endl;
	//cout<<temp<<endl;
	ans+=temp;
}

int main()
{
	ans=0;
	memset(w,0,sizeof w);
	cin>>s>>k;
	init();
	for(int i=0;i<s.length();i++)
	{
		ans+= (i+1)*w[s[i]-'a'+1];
	}
	solve();
	printf("%d",ans);
	return 0;
}

C. DZY Loves Sequences

time limit per test
1 second
memory limit per test
256 megabytes
input
standard input
output
standard output

DZY has a sequence a, consisting of n integers.

We'll call a sequence ai, ai + 1, ..., aj (1 ≤ i ≤ j ≤ n) a subsegment of the sequence a. The value (j - i + 1) denotes the length of the subsegment.

Your task is to find the longest subsegment of a, such that it is possible to change at most one number (change one number to any integer you want) from the subsegment to make the subsegment strictly increasing.

You only need to output the length of the subsegment you find.

Input

The first line contains integer n (1 ≤ n ≤ 105). The next line contains n integers a1, a2, ..., an (1 ≤ ai ≤ 109).

Output

In a single line print the answer to the problem — the maximum length of the required subsegment.

Sample test(s)
input
6
7 2 3 1 5 6
output
5
Note

You can choose subsegment a2, a3, a4, a5, a6 and change its 3rd element (that is a4) to 4.


这道题的意思呢是说有这么许多的数,问你如果只让你最多改一个数字,可以令这串数字中最长的一个满足严格递增的子串长度。

这样用dp来O(n)内给现有数据分段是必须的,然后就是考虑各种情况了。我想到的有:(事实证明想的繁了……)

1\ 当前段落为1个数字的时候

2\ 前一个段落为1个数字的时候

3\ 当前和前一个都为1个数字的时候

4\ 

5\

好多好多,反正就是很烦……

这道题我在Pretest的时候分分钟秒掉了,但是最后说我错掉了……才知道……原来还有这一手……边缘数据和其他一些可能错误的点会放在完整数据里:

#include <cmath>   
#include <vector>  
#include <cctype>  
#include <cstdio>  
#include <string>  
#include <cstdlib>  
#include <cstring>  
#include <iostream>  
#include <algorithm>  
#define update(x) ans=(x>ans)?x:ans
using namespace std;
int n,ccnt,a[100001],dp[111111];
int chain[100001]; //length of each sequence
int pos[100001];

void init()
{
	ccnt=0;
	memset(a,0,sizeof a);
	memset(dp,0,sizeof dp);
	memset(pos,0,sizeof pos);
	memset(chain,0,sizeof chain);
	for(int i=0;i<n;i++)
	{
		scanf("%d",&a[i]);
		if(i)
		{
			if(a[i]>a[i-1])dp[i]=dp[i-1]+1;
			else 
			{
				chain[ccnt]=dp[i-1]+1;
				pos[ccnt]=i-1;
				ccnt++;
				//cout<<dp[i-1]<<":m1: \t";
				dp[i]=0;
			}
		}
	}
	chain[ccnt]=dp[n-1]+1;
	pos[ccnt]=n-1;
}

int solve()
{
	int ans=0;
	if(ccnt==0)update(chain[0]);
	else 
	{
		update(chain[0]+1);
		for(int i=1;i<=ccnt;i++)
		{
			//cout<<chain[i]<<"\t"<<pos[i]<<endl;
			if(chain[i]==1)	//I am 1
			{
				if(a[pos[i-1]]+1<a[pos[i+1]-chain[i+1]+1])	//then change chain[i]
				update(chain[i+1]+chain[i-1]+1);
				else update(chain[i-1]+1);
			}
			else if(chain[i-1]==1)// my front is 1
				{
					update(chain[i]+1);
				}
			else if(chain[i+1]==1);// my back is 1 _for i+1 judgement
			else if(a[pos[i-1]]+1<a[pos[i]-chain[i]+2]) 	//then change chain[i]'s 1st
				update(chain[i]+chain[i-1]);
			else update(chain[i]+1);
		}
   }
	return ans;
}

int main()
{
	scanf("%d",&n);
	init();
	cout<<solve();
	return 0;
}


Test: # 17, time:  15 ms., memory:  1612 KB, exit code:  0, checker exit code:  1, verdict:  WRONG_ANSWER
Checker Log
wrong answer 1st numbers differ - expected: '46213', found: '31904'

看了看,全是极限数据,那么为什么这里就会是错误的呢,仔细思考,难不成存在某种可怕的溢出?

于是改成longlong,但是依然WA at 17……

#include <cmath>   
#include <vector>  
#include <cctype>  
#include <cstdio>  
#include <string>  
#include <cstdlib>  
#include <cstring>  
#include <iostream>  
#include <algorithm>  
#define update(x) ans=(x>ans)?x:ans
using namespace std;
typedef long long ll;
ll n,ccnt,a[100001],dp[111111];
ll chain[100001]; //length of each sequence
ll pos[100001];

void init()
{
	ccnt=0;
	memset(a,0LL,sizeof a);
	memset(dp,0LL,sizeof dp);
	memset(pos,0LL,sizeof pos);
	memset(chain,0LL,sizeof chain);
	for(ll i=0;i<n;i++)
	{
		scanf("%d",&a[i]);
		if(i)
		{
			if(a[i]>a[i-1])dp[i]=dp[i-1]+1;
			else 
			{
				chain[ccnt]=dp[i-1]+1;
				pos[ccnt]=i-1;
				ccnt++;
				//cout<<dp[i-1]<<":m1: \t";
				dp[i]=0;
			}
		}
	}
	chain[ccnt]=dp[n-1]+1;
	pos[ccnt]=n-1;
}

ll solve()
{
	ll ans=0;
	if(ccnt==0)update(chain[0]);
	else 
	{
		update(chain[0]+1);
		for(int i=1;i<=ccnt;i++)
		{
			//cout<<chain[i]<<"\t"<<pos[i]<<endl;
			if(chain[i]==1)	//I am 1
			{
				if(a[pos[i-1]]+1<a[pos[i+1]-chain[i+1]+1])	//then change chain[i]
				update(chain[i+1]+chain[i-1]+1);
				else update(chain[i-1]+1);
			}
			else if(chain[i-1]==1)// my front is 1
				{
					update(chain[i]+1);
				}
			else if(chain[i+1]==1);// my back is 1 _for i+1 judgement
			else if(a[pos[i-1]]+1<a[pos[i]-chain[i]+2]) 	//then change chain[i]'s 1st
				update(chain[i]+chain[i-1]);
			else update(chain[i]+1);
		}
   }
	return ans;
}

int main()
{
	cin>>n;
	init();
	cout<<solve();
	return 0;
}


后来整理整理,其实只有四条需要注意的……

 if(f[i]==n)ans=max(ans,f[i]);
        else ans=max(ans,f[i]+1);
        if(a[i-f[i]+1]>a[i-f[i]-1]+1)ans=max(ans,f[i]+f[i-f[i]]);
        if(a[i-f[i]+2]>a[i-f[i]]+1)ans=max(ans,f[i]+f[i-f[i]]);

Code:

#include <cmath>   
#include <vector>  
#include <cctype>  
#include <cstdio>  
#include <string>  
#include <cstdlib>  
#include <cstring>  
#include <iostream>  
#include <algorithm>  
#define inf 999999
#define maxn 100005
#define update(x) ans=(x>ans)?x:ans
using namespace std;
int n,a[maxn],f[maxn];
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)scanf("%d",&a[i]);
    f[1]=1;
    for(int i=2;i<=n;i++)
    {
        f[i]=1;if(a[i]>a[i-1])f[i]=f[i-1]+1;
    }
    int ans=-inf;
    for(int i=1;i<=n;i++)
    {
        if(f[i]==n) update(f[i]);
        else update(f[i]+1);
        if(a[i-f[i]+1]>a[i-f[i]-1]+1) update(f[i]+f[i-f[i]]);
        if(a[i-f[i]+2]>a[i-f[i]]+1) update(f[i]+f[i-f[i]]);
    }
    printf("%d\n",ans);
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

糖果天王

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值