A
思路:
d p [ i ] dp[i] dp[i]代表以 a [ i ] a[i] a[i]结尾的序列最长有多长,然后对于每个 d p [ i ] dp[i] dp[i]之前的 1 1 1到 i − 1 i-1 i−1遍历找一个最大值进行取代即可
代码:
#include<stdio.h>
#include<math.h>
#include<algorithm>
#define LL long long
using namespace std;
const int mod=998244353;
const int MAXN=3e5+7;
LL a[MAXN],dp[MAXN],c[MAXN];
int main()
{
int n;
while(~scanf("%d",&n)){
for(int i=0;i<n;i++) scanf("%lld",&a[i]);
LL ans=-MAXN;
for(int i=0;i<n;i++){
dp[i]=1;
for(int j=0;j<i;j++){
if(a[i]>a[j]) dp[i]=max(dp[j]+1,dp[i]);
}
ans=max(ans,dp[i]);
}
printf("%lld\n",ans);
}
return 0;
}
C
思路
( k / 2 ) ∗ a − ( k / 2 ) ∗ b + ( k % 2 ) ∗ a (k/2)*a-(k/2)*b+(k\%2)*a (k/2)∗a−(k/2)∗b+(k%2)∗a算出数据即可
代码
#include<stdio.h>
#include<math.h>
#include<algorithm>
#define LL long long
using namespace std;
const int mod=998244353;
const int MAXN=3e5+7;
LL a[MAXN],dp[MAXN],c[MAXN];
int main()
{
int n;scanf("%d",&n);
while(n--){
LL a,b,k;
scanf("%lld%lld%lld",&a,&b,&k);
printf("%lld\n",(k/2)*a-(k/2)*b+(k%2)*a);
}
return 0;
}
D
思路
满足 101 101 101的就把1往前提然后计数即可
代码
#include<stdio.h>
#include<math.h>
#include<algorithm>
#define LL long long
using namespace std;
const int mod=998244353;
const int MAXN=2e6+7;
int vis[MAXN],k[MAXN],a[MAXN];
int main()
{
int n;
scanf("%d",&n);
for(int i=0;i<n;i++) scanf("%d",&a[i]);
int ans=0;
for(int i=1;i<n;i++){
if(a[i]==0&&a[i-1]==1&&a[i+1]==1){
a[i+1]=0;
ans++;
}
}
printf("%d\n",ans);
return 0;
}
E
思路
既然是要求去掉一个数后存在一个数等于其他所有数之和,那么剩下的所有数之和肯定是偶数。
两种思路,二分找数或者设置映射判断是否存在。在判断遍历去掉时我们需要注意一点,如果去掉的这个数有两个,那么我们需要特判一下。
代码
#include<stdio.h>
#include<math.h>
#include<algorithm>
#define LL long long
using namespace std;
const int mod=998244353;
const int MAXN=2e6+7;
int vis[MAXN],k[MAXN],a[MAXN];
int main()
{
int n;
while(~scanf("%d",&n)){
LL sum=0;
for(int i=0;i<n;i++){
scanf("%d",&a[i]);
vis[a[i]]++;
sum+=a[i];
}
int cnt=0;
for(int i=0;i<n;i++){
LL temp=sum-a[i];
if((temp<=MAXN)&&(temp%2==0)){
temp/=2;
if(temp!=a[i]&&vis[temp]>=1) k[cnt++]=i+1;
else if(vis[temp]>=2) k[cnt++]=i+1;
}
}
printf("%d\n",cnt);
for(int i=0;i<cnt;i++) printf("%d ",k[i]);
}
return 0;
}
F
思路
二分求存在的子序列的遍数最大值,然后往外出数即可。去重可以用deque也可以像我一样用映射。
代码
#include<stdio.h>
#include<math.h>
#include<algorithm>
#define LL long long
using namespace std;
const int mod=998244353;
const int MAXN=2e6+7;
struct v{
int pos,wi;
}vis[MAXN];
int n,k;
struct da{
int w,num;
}d[MAXN];
bool cmp(da a,da b){return a.num>b.num;}
bool check(int mid,int cnt){
int sum=0;
for(int i=0;i<cnt;i++) sum+=d[i].num/mid;
return sum>=k;
}
int main()
{
int temp,cnt=0;
scanf("%d%d",&n,&k);
for(int i=0;i<n;i++){
scanf("%d",&temp);
if(!vis[temp].wi){d[cnt++].w=temp;vis[temp].pos=cnt-1;}
vis[temp].wi++;
d[vis[temp].pos].num=vis[temp].wi;
}
sort(d,d+cnt,cmp);
int l=1,r=1e9,ans=0;
while(l<=r){
int mid=(l+r)/2;
if(check(mid,cnt)) l=mid+1;
else r=mid-1,ans=r;
}
for(int i=0;i<cnt;i++){
if(k==0) break;
int t=d[i].num/ans;
while(t--){
printf("%d ",d[i].w),k--;
if(k==0) break;
}
}
return 0;
}