A题题目链接
有t组测试数据,每组测试数据有n个数,可以选择第i个数 a[i] 且 a[i] != a[i+1],那么就可以把这两个数加起来,得到一个新的值放到当前位置。
例如:[7 3 4 7] ,当选择i = 2时候 a[2] = 3,a[3] = 4 -> [7,7,7]
求数组的最短长度是多少?
每次操作都能使数组位数-1,只有当出现n个数字都是相同的时候,就没办法进行上面的选择操作,即数组位数始终只能是n;其余情况均可减到数组只剩一个的时候
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
typedef long long ll;
const int maxn = 2e5 + 10;
const int INF = 0x3f3f3f3f;
int t,n;
int a[maxn];
int main()
{
scanf("%d",&t);
while(t--)
{
int flag = 0;
scanf("%d",&n);
scanf("%d",&a[1]);
for(int i = 2; i <= n; i++)
{
scanf("%d",&a[i]);
if(a[i] != a[i-1])
flag = 1;
}
if(flag)
printf("1\n");
else
printf("%d\n",n);
}
return 0;
}
B题题目链接
给t组数据,每组数据有n个数,k次操作,每次操作选择当前数组最大的数d,使1 ~ n的a[i] = d - a[i].
输出经过了k次操作之后数组所有的数是什么样的。
找规律,会发现k为奇数的时候,其数组值为原数组最大的d1 减去 原数组a[i],k为偶数的时候,其数组值为第一次变化后的数组最大值d2 减去 第一次变化后的a[i]。
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
typedef long long ll;
const int maxn = 2e5 + 10;
const int INF = 0x3f3f3f3f;
int t,n;
ll k,a[maxn];
int main()
{
scanf("%d",&t);
while(t--)
{
ll maxx1 = -1e10, maxx2 = -1e10;
scanf("%d%d",&n,&k);
for(int i = 1; i <= n; i++)
{
scanf("%lld",&a[i]);
maxx1 = max(maxx1,a[i]);
}
for(int i = 1; i <= n; i++)
{
a[i] = maxx1 - a[i];
maxx2 = max(maxx2,a[i]);
}
if(k % 2 == 1)
{
for(int i = 1; i <= n; i++)
printf("%lld ",a[i]);
}
else
{
for(int i = 1; i <= n; i++)
printf("%lld ",maxx2 - a[i]);
}
printf("\n");
}
return 0;
}
C题题目链接
有t组测试数据,每组数据有n个数,每次可以选择连续的相同数字,使他们+1;
例如 : 3 4 4 5 7 --可以先选择[1,1]–> 4 4 4 5 7 --然后可以在选择[1,3]–> 5 5 5 5 7
问你能用最少多少次选择,使得数组成为数值不下降的数组(a[i] <= a[i+1])?
当出现后一个数比前一个数小的时候,我们就ans += a[i+1] - a[i];
例如:5 9 3 1 --先把1加到3,再把连续的3加到9–> ans += (9 - 3) + (3 - 1);
当后一个数比前一个数大的时候,我们就不变,因为后一个数比前一个数大要么是已经满足条件,要么是可以把前一个数加到后一个数这么大之后在一起累加;
例如:①5 2 3 7 --> 5 3 3 7 --> 5 4 4 7 -> 5 5 5 7 ans = 5 - 2;
②5 2 3 1 7 --> 5 3 3 1 7 --> 5 3 3 2 7 --> 5 3 3 3 7 -->……
也就是每一个小于它前面的数要加到和他前面那个数的高度相同即可
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
typedef long long ll;
const int maxn = 2e5 + 10;
const int INF = 0x3f3f3f3f;
int t,n;
ll a[maxn];
int main()
{
scanf("%d",&t);
while(t--)
{
ll ans = 0;
scanf("%d",&n);
for(int i = 1; i <= n; i++)
scanf("%lld",&a[i]);
for(int i = 2; i <= n; i++)
{
if(a[i] < a[i-1])
ans += a[i-1] - a[i];
}
printf("%lld\n",ans);
}
return 0;
}
D题题目链接
t组测试数据,每组测试数据有n个字符,n个字符围成一个圆环,"L"代表着当前玩家向左攻击,"R"代表当前玩家向右攻击,问最少经过多少次变化,能够使每一个被攻击的玩家满足:①没有玩家攻击他,他可以选择攻击左右两侧任意一个玩家。②有一个玩家攻击他,他就必须攻击那个玩家。③左右两侧两个玩家攻击他,他就选择两个玩家中的任意一个进行攻击。
首先根据题意,我们知道不能出现连续三个相同的字符;
因为数据量很大,所以就分为三种情况:
全是同一个字符;首尾相等;首尾不等。
然后找规律。
在利用一下前缀和的思想,记录每一个相同字符的连续数量。
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
typedef long long ll;
const int maxn = 2e5 + 10;
const int INF = 0x3f3f3f3f;
int t,n,sum[maxn];
char a[maxn];
int main()
{
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
int ans = 0,flag = 1;
for(int i = 1; i <= n; i++)
{
scanf(" %c",&a[i]);
}
sum[n] = 1;
for(int i = n-1; i >= 1; i--)
{
sum[i] = 1;
if(a[i] == a[i + 1])
{
sum[i] += sum[i+1];
if(flag)
sum[n] = sum[i];
}
else
flag = 0;
}
if(sum[1] == n)
{
if(n % 3 == 0)
printf("%d\n",n/3);
else
printf("%d\n",n/3 + 1);
continue;
}
else{
if(a[1] == a[n])
{
int k = sum[1] + 1;
sum[1] += sum[n];
ans += sum[1] / 3;
n -= sum[n];
while(k <= n)
{
ans += sum[k] / 3;
k += sum[k];
}
}
else{
int k = 1;
while(k <= n)
{
ans += sum[k] / 3;
k += sum[k];
}
}
}
printf("%d\n",ans);
}
return 0;
}