B Beauty Values
题目解读:简单的DP。一个有n个数字的序列,求它所有子序列贡献值的和。子序列贡献值为它包含不同数字的个数。如1,2,1这个序列的贡献值为2。1,3。这个序列的贡献值为2。
a[i]存序列第i个数字。p[a[i]]存上一个a[i]出现的位置。dp[i]存所有以第i个数结尾的所有子序列的贡献值的和。
样例 1 2 1 3
如 d[1]=1,对应子序列为 1 1 d[2]=1+2,对应子序列为 2 2. 1 2. d[3]=1+2+2.对应子序列为1 1. 2,1. 1 2 1 。注意p[a[i]]的作用在后面这两个子序列出现。在序列 1 2 1 中,既然1 在之前的1 2 子序列已经出现,现在再出现也没什么用,即不增加贡献值,而我们之前把它加上了,所以要减去。推广一下,加上(不考虑相等之前有跟它相等的数)增加的贡献值,再减去误加的。就是两个相同a[i]的差值。
d[4]=1+2+3+3 对应子序列为 3 3 1 3 2 1 3 1 2 1 3
注意 dp数组和贡献值总和ans都开long long.
AC代码:
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+10;
typedef long long ll;
int a[maxn],p[maxn];
ll ans,dp[maxn];
int main()
{
int n;cin>>n;
for(int i=1;i<=n;i++)
cin>>a[i];
for(int i=1;i<=n;i++)
{
dp[i]=dp[i-1]+i;
dp[i]-=p[a[i]];
p[a[i]]=i;
ans+=dp[i];
}
cout<<ans<<endl;
return 0;
}
G Gemstones
题目解读:模拟一下栈即可。
注意误区:一个字符串只能有一个值。它既是最大,也是最小。不要被题目中的最大值误导了,乱模拟,(⊙o⊙)…就是这样,把自己给模拟迷了╮(╯▽╰)╭。
AC代码
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+10;
char a[maxn],b[maxn];
int main()
{
int m=0,ans=0;
cin>>a;int l=strlen(a);
for(int i=0;i<l;i++)
{
b[m++]=a[i];
if(m<=1) continue;
if(b[m-1]==b[m-2]&&b[m-1]==b[m-3]) ans++,m-=3;
}
cout<<ans<<endl;
return 0;
}