当前位置: 代码迷 >> 综合 >> BestCoder Round #86题解报告
  详细解决方案

BestCoder Round #86题解报告

热度:37   发布时间:2023-12-12 10:26:02.0

此文章可以使用目录功能哟↑(点击上方[+])

许久不hack,连hack都hack不来了...

链接→BestCoder Round #86

 Problem 1001 Price List

Accept: 0    Submit: 0
Time Limit: 2000/1000 MS (Java/Others)    Memory Limit : 262144/131072 K (Java/Others)

 Problem Description

There are n shops numbered with successive integers from 1 to n in Byteland. Every shop sells only one kind of goods, and the price of the i-th shop's goods is vi.
Every day, Byteasar will purchase some goods. He will buy at most one piece of goods from each shop. Of course, he can also choose to buy nothing. Back home, Byteasar will calculate the total amount of money he has costed that day and write it down on his account book.
However, due to Byteasar's poor math, he may calculate a wrong number. Byteasar would not mind if he wrote down a smaller number, because it seems that he hadn't used too much money.
Please write a program to help Byteasar judge whether each number is sure to be strictly larger than the actual value.
在Byteland一共有n家商店,编号依次为1到n。每家商店只会卖一种物品,其中第i家商店的物品单价为v?i。
Byteasar每天都会进行一次购物,他会在每家商店购买最多一件物品,当然他也可以选择什么都不买。回家之后,Byteasar会把这一天购物所花的钱的总数记录在账本上。
Byteasar的数学不好,他可能会把花的钱记少,也可能记多。Byteasar并不介意记少,因为这样看上去显得自己没花很多钱。
请写一个程序,帮助Byteasar判断每条记录是否一定记多了。

 Input

The first line of the input contains an integer T (1≤T≤10), denoting the number of test cases.
In each test case, the first line of the input contains two integers n,m (1≤n,m≤100000), denoting the number of shops and the number of records on Byteasar's account book.
The second line of the input contains n integers v1,v2,...,vn (1≤vi≤100000), denoting the price of the i-th shop's goods.
Each of the next m lines contains an integer q (0≤q≤10^18), denoting each number on Byteasar's account book.
输入的第一行包含一个正整数T(1≤T≤10),表示测试数据的组数。
对于每组数据,第一行包含两个正整数n,m(1≤n,m≤100000),表示商店的个数和记录的个数。
第二行包含n个正整数v?i(1≤vi≤100000),依次表示每家商店的物品的单价。
接下来m行,每行包含一个整数q(0≤q≤10^18),表示一条记录。

 Output

For each test case, print a line with m characters. If the i-th number is sure to be strictly larger than the actual value, then the i-th character should be '1'. Otherwise, it should be '0'.

对于每组数据,输出一行m个字符,依次回答每个询问。如果一定记多了,请输出'1',否则输出'0'。

 Sample Input

1
3 3
2 5 4
1
7
10000

 Sample Output

001

 Problem Idea

解题思路:

【题意】
题意请看上述中文题面


【类型】
水题

【分析】
题目很关键的一句话是

Byteasar并不介意把花的钱记少(多么自欺欺人的一个人)

然后题目问是不是一定记多了

简单想想,什么情况下可以自欺欺人呢?

很简单,因为每个商店的商品最多买1件,那我全买的时候花的钱肯定是最多的

而只要记录的钱数比这个值小,那我都可以自欺欺人一波,反正你不能拿我怎么样

所以此题只需要求出所有商品价值之和,再与Byteasar每天记录的钱做比较即可

另外此题需要注意的就是数据大小了,我看到有人q定义了__int64,但是居然用%d输入,醉了,hack忘记回车,一直说我数据非法,难过

【时间复杂度&&优化】
O(nT)

题目链接→HDU 5804 Price List

 Source Code

/*Sherlock and Watson and Adler*/
#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<queue>
#include<stack>
#include<math.h>
#include<vector>
#include<map>
#include<set>
#include<cmath>
#include<complex>
#include<string>
#include<algorithm>
#include<iostream>
#define eps 1e-9
#define LL long long
#define bitnum(a) __builtin_popcount(a)
using namespace std;
const int N = 10005;
const int M = 16;
const int inf = 1000000007;
const int mod = 110119;
int main()
{int t,n,m,s,i;__int64 ans,q;scanf("%d",&t);while(t--){ans=0;scanf("%d%d",&n,&m);for(i=0;i<n;i++){scanf("%d",&s);ans+=s;}for(i=0;i<m;i++){scanf("%I64d",&q);if(q>ans)printf("1");elseprintf("0");}puts("");}return 0;
}

 Problem 1002 NanoApe Loves Sequence

Accept: 0    Submit: 0
Time Limit: 2000/1000 MS (Java/Others)    Memory Limit : 262144/131072 K (Java/Others)

 Problem Description

NanoApe, the Retired Dog, has returned back to prepare for the National Higher Education Entrance Examination!

In math class, NanoApe picked up sequences once again. He wrote down a sequence with n numbers on the paper and then randomly deleted a number in the sequence. After that, he calculated the maximum absolute value of the difference of each two adjacent remained numbers, denoted as F.

Now he wants to know the expected value of F, if he deleted each number with equal probability.

退役狗 NanoApe 滚回去学文化课啦!

在数学课上,NanoApe 心痒痒又玩起了数列。他在纸上随便写了一个长度为 n 的数列,他又根据心情随便删了一个数,这样他得到了一个新的数列,然后他计算出了所有相邻两数的差的绝对值的最大值。

他当然知道这个最大值会随着他删了的数改变而改变,所以他想知道假如全部数被删除的概率是相等的话,差的绝对值的最大值的期望是多少。

 Input

The first line of the input contains an integer T, denoting the number of test cases.

In each test case, the first line of the input contains an integer n, denoting the length of the original sequence.

The second line of the input contains n integers A1,A2,...,An, denoting the elements of the sequence.

1≤T≤10, 3≤n≤100000, 1≤Ai≤10^9

第一行为一个正整数 T,表示数据组数。

每组数据的第一行为一个整数 n。

第二行为 n 个整数 A?i,表示这个数列。

1≤T≤10, 3≤n≤100000, 1≤A?i≤10^?9

 Output

For each test case, print a line with one integer, denoting the answer.

In order to prevent using float number, you should print the answer multiplied by n.

对于每组数据输出一行一个数表示答案。

为防止精度误差,你需要输出答案乘上 n 后的值。

 Sample Input

1
4
1 2 3 4

 Sample Output

6

 Problem Idea

解题思路:

【题意】
长度为n的序列,等可能性地删除其中一个数,问得到的新数列的所有相邻两数的差的绝对值的最大值的期望为多少


【类型】
优化

【分析】
题目很贴心地帮我们将期望的分母去掉了

那此题就转化成了求所有可能的新序列的相邻两数的差的绝对值的最大值之和

新序列相对于原来的序列而言,就相当于挖掉了一个数,将该数的左边和右边拼凑成新序列

那我们只需知道左边的最大值与右边的最大值,再和拼接处产生的差值比较一下,就可以知道新序列的最大值

即令l[i]表示前i个数两两相邻差值的绝对值的最大值,r[i]表示i到n范围内两两相邻差值的绝对值的最大值

那么枚举删除第i个数,加上删除该数时的序列最大值即可

ans+=max(abs(s[i+1]-s[i-1]),max(l[i-1],r[i+1]))

注意,在删除序列首尾的数时,要特判一下

【时间复杂度&&优化】
O(nT)

题目链接→HDU 5805 NanoApe Loves Sequence

 Source Code

/*Sherlock and Watson and Adler*/
#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<queue>
#include<stack>
#include<math.h>
#include<vector>
#include<map>
#include<set>
#include<cmath>
#include<complex>
#include<string>
#include<algorithm>
#include<iostream>
#define eps 1e-9
#define LL long long
#define bitnum(a) __builtin_popcount(a)
using namespace std;
const int N = 100005;
const int M = 16;
const int inf = 1000000007;
const int mod = 110119;
int s[N],l[N],r[N];
int main()
{int t,n,i;__int64 ans;scanf("%d",&t);while(t--){ans=0;memset(l,0,sizeof(l));memset(r,0,sizeof(r));scanf("%d",&n);for(i=0;i<n;i++)scanf("%d",&s[i]);for(i=1;i<n;i++)l[i]=max(abs(s[i]-s[i-1]),l[i-1]);for(i=n-2;i>=0;i--)r[i]=max(abs(s[i+1]-s[i]),r[i+1]);for(i=0;i<n;i++)if(i==0)ans+=r[i+1];else if(i==n-1)ans+=l[i-1];elseans+=max(abs(s[i+1]-s[i-1]),max(l[i-1],r[i+1]));printf("%I64d\n",ans);}return 0;
}


 Problem 1003 NanoApe Loves Sequence Ⅱ

Accept: 0    Submit: 0
Time Limit: 4000/2000 MS (Java/Others)    Memory Limit : 262144/131072 K (Java/Others)

 Problem Description

NanoApe, the Retired Dog, has returned back to prepare for for the National Higher Education Entrance Examination!

In math class, NanoApe picked up sequences once again. He wrote down a sequence with n numbers and a number m on the paper.

Now he wants to know the number of continous subsequences of the sequence in such a manner that the k-th largest number in the subsequence is no less than m.

Note : The length of the subsequence must be no less than k.

退役狗 NanoApe 滚回去学文化课啦!

在数学课上,NanoApe 心痒痒又玩起了数列。他在纸上随便写了一个长度为 n 的数列,他又根据心情写下了一个数 m。

他想知道这个数列中有多少个区间里的第 k 大的数不小于 m,当然首先这个区间必须至少要有 k 个数啦。

 Input

The first line of the input contains an integer T, denoting the number of test cases.

In each test case, the first line of the input contains three integers n,m,k.

The second line of the input contains n integers A1,A2,...,An, denoting the elements of the sequence.

1≤T≤10, 2≤n≤200000, 1≤k≤n/2, 1≤m,Ai≤10^9

第一行为一个正整数 T,表示数据组数。
每组数据的第一行为三个整数 n,m,k。
第二行为 nn 个整数 A?i,表示这个数列。
1≤T≤10, 2≤n≤200000, 1≤k≤n/2, 1≤m,A?i≤10^9
??

 Output

For each test case, print a line with one integer, denoting the answer.

对于每组数据输出一行一个数表示答案。

 Sample Input

1
7 4 2
4 2 7 7 6 5 1

 Sample Output

18

 Problem Idea

解题思路:

【题意】
给定一个长度为n的数列

问有多少个区间的第k大数>=m


【类型】
尺取法

【分析】
看到区间第k大,貌似是个很常见的问题

然而这跟那些区间第k大问题并没有直接关系

首先,要先知道,第k大,是从大到小排序后第k个(不去重)

那简单了,我们只要记录以第i个数作为区间左端点时,右端点延伸到何处能够满足区间内有k个数>=m即可,因为右端点再往右延伸必定满足区间内有k个数>=m

这点可以通过尺取法实现,异或者叫做双指针

那么最终结果只需枚举左端点,加上右端点可以取的个数即可


【时间复杂度&&优化】
O(nT)

题目链接→HDU 5806 NanoApe Loves Sequence Ⅱ

 Source Code

/*Sherlock and Watson and Adler*/
#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<queue>
#include<stack>
#include<math.h>
#include<vector>
#include<map>
#include<set>
#include<cmath>
#include<complex>
#include<string>
#include<algorithm>
#include<iostream>
#define eps 1e-9
#define LL long long
#define bitnum(a) __builtin_popcount(a)
using namespace std;
const int N = 200005;
const int M = 16;
const int inf = 1000000007;
const int mod = 110119;
int s[N],r[N];
int main()
{int t,n,m,k,i,j,c;__int64 ans;scanf("%d",&t);while(t--){ans=0;c=0;scanf("%d%d%d",&n,&m,&k);for(i=0;i<n;i++){scanf("%d",&s[i]);r[i]=n;}for(j=i=0;i<n;i++){if(s[i]>=m)c++;while(c==k){r[j]=i;if(s[j]>=m)c--;j++;}}for(i=0;i<n;i++)ans+=(n-r[i]);printf("%I64d\n",ans);}return 0;
}

菜鸟成长记

  相关解决方案