THIRD PROGRAMMING CONTEST 2023 ALGO(AtCoder Beginner Contest 318)

THIRD PROGRAMMING CONTEST 2023 ALGO(AtCoder Beginner Contest 318)

A - Full Moon

思路:模拟

直接模拟即可,找到以m开始每一次可以调p的距离终点为n的次数

c++ 复制代码
#include<bits/stdc++.h>
using namespace std;
int main(){
    int n,m,q;cin>>n>>m>>q;
    int res=1;
    while(n>m){
        m+=q;
        res++;
    }
    if(n<m)res--;
    cout<<res;
}

B - Overlapping sheets

思路:暴力

由于矩阵不是很大,之间标记每一组能覆盖的点即可

c++ 复制代码
#include<bits/stdc++.h>
using namespace std;
int a[110][110];
int main(){
    int n;
    int res=0;
    cin>>n;
    while(n--){
        int x,y,x1,y1;
        cin>>x>>y>>x1>>y1;
        for(int i=x;i<=y-1;i++){
            for(int j=x1;j<=y1-1;j++)a[i][j]++;
        }
    }
    
    for(int i=0;i<=100;i++){
        for(int j=0;j<=100;j++)if(a[i][j]>0)res++;
    }
    cout<<res;
}

C - Blue Spring

思路:贪心+排序

我们先排个序,然后计算d天花费和特价票的价格的大小,如果特价更优惠就跟新需要花费的钱

c++ 复制代码
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=2e6+7;
int a[N],s[N];
signed main(){
    int n,d,p;
    cin>>n>>d>>p;
    int sum=0;
    for(int i=1;i<=n;i++){
        cin>>a[i];
        sum+=a[i];
    }
    sort(a+1,a+1+n);
    for(int i=1;i<=n;i++){
        s[i]=s[i-1]+a[i];
    }
    int id=n;
    while(id){
        if(id-d<0)d=id;
        int m=s[id]-s[id-d];
        //cout<<m<<endl;
        if(m>p){
            sum-=(m-p);
            id=id-d;
        }else break;
    }
   // cout<<id<<endl;
    cout<<sum;
}

D - General Weighted Max Matching

思路:dfs

一眼看过去这是一般图的最大权独立集,根本没啥多项式做法。

所以就直接爆搜的就好了,也就是对于每一个点找它匹配的点,需要注意的是可以有点不匹配边。

这样的复杂度就是 O(N!!)O(N!!) 显然可以过。

c++ 复制代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N = 20;
int n,match[N],d[N][N],ans,sum;
void dfs(int now){
	if(now == n + 1){
		ans = max(ans,sum);
		return;
	}
	if(match[now]){
		dfs(now+1);
		return;
	}
	for(int i=now+1; i<=n; i++){
		if(match[i])	continue;
		match[now] = i,match[i] = now;
		sum += d[now][i];
		dfs(now+1);
		match[now] = match[i] = 0;
		sum -= d[now][i];
	}
	dfs(now+1);
}
signed main(){
	scanf("%lld",&n);
	for(int i=1; i<=n; i++){
		for(int j=i+1; j<=n; j++){
			scanf("%lld",&d[i][j]);
		}
	}
	dfs(1);
	printf("%lld\n",ans);
	return 0;
}

E - Sandwiches

思路:前后缀数组

由于数有105,我们只能枚举其中一个。要么枚举 i要么枚举 j。分别考虑后发现枚举 j简单一点。

如果枚举下标i会发现比较难计算,对于当前的 ai,那么对于之后的每个 ak都要考虑它们之间的其他数的个数,感觉复杂度会比较大。

考虑枚举下标j,剩下的就是考虑 j左边和 j右边的相同数。这个j对答案的贡献就是 ∑x≠ajlx×rx,其中 lx表示 j左边 x(是值,不是下标)的个数, rx就是右边的 x的个数。

考虑当 j移动时,只有 aj和 aj+1这两个数的个数发生变化。因此我们事先维护 ∑的值,∑−laj×raj就是此时的 j对答案的贡献。转移时通过加减那两个数的贡献,就得到 j移动到下一个数时的 ∑的值。然后累计就是答案了

c++ 复制代码
#include<bits/stdc++.h>
using namespace std;
#define int long long
signed main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int n;cin>>n;
    vector<int>a(n+10,0);
    vector<int>l(n+10,0),r(n+10,0);
    for(int i=0;i<n;i++){
        int x;
        cin>>x;
        a[i]=x;
        r[a[i]]++;
    }
    int ans=0;
    int res=0;
    for(int i=0;i<n;i++){
        res-=1ll*(l[a[i]]*r[a[i]]);
        ans+=res;
        r[a[i]]--;
        l[a[i]]++;
        res+=1ll*(l[a[i]]*r[a[i]]);
    }
    cout<<ans;
}
相关推荐
自身就是太阳5 分钟前
2024蓝桥杯省B好题分析
算法·职场和发展·蓝桥杯
孙小二写代码28 分钟前
[leetcode刷题]面试经典150题之1合并两个有序数组(简单)
算法·leetcode·面试
QXH20000029 分钟前
数据结构—单链表
c语言·开发语言·数据结构
imaima66630 分钟前
数据结构----栈和队列
开发语言·数据结构
little redcap34 分钟前
第十九次CCF计算机软件能力认证-1246(过64%的代码-个人题解)
算法
David猪大卫1 小时前
数据结构修炼——顺序表和链表的区别与联系
c语言·数据结构·学习·算法·leetcode·链表·蓝桥杯
Iceberg_wWzZ1 小时前
数据结构(Day14)
linux·c语言·数据结构·算法
夏天天天天天天天#1 小时前
求Huffman树及其matlab程序详解
算法·matlab·图论
Infedium1 小时前
优数:助力更高效的边缘计算
算法·业界资讯
student.J1 小时前
傅里叶变换
python·算法·傅里叶