2023广东省赛
Dashboard - The 2023 Guangdong Provincial Collegiate Programming Contest - Codeforces
A |
⭐ |
枚举 |
C |
⭐ |
循环 |
K |
⭐⭐ |
搜索 |
I |
⭐⭐ |
二分 |
D |
⭐⭐ |
贪心 |
M |
⭐⭐ |
几何 |
B |
⭐⭐⭐ |
单调队列优化DP |
E |
⭐⭐⭐ |
字符串 思维 |
F<---- |
⭐⭐⭐ |
线段树 二分 |
J |
⭐⭐⭐⭐ |
数学 |
H |
⭐⭐⭐⭐ |
建图 |
G |
⭐⭐⭐⭐ |
思维 |
L |
⭐⭐⭐⭐ |
图论 |
A - Programming Contest(签到)
#include <bits/stdc++.h>
#define bug cout << "***************" << endl
#define look(x) cout << #x << " -> " << x << endl
#define endl '\n'
#define int long long
#define YES cout << "YES" << endl;
#define NO cout << "NO" << endl;
using namespace std;
typedef pair<int, int> PII;
constexpr int N = 1e5 + 10 , INF = 2e9;
int n,m;
int ans;
int a[N];
void solve()
{
cin>>n;
int k;
cin>>k;
for(int i=0;i<k;i++)
cin>>a[i];
cin>>m;
int cnt=0;
for(int i=0;i<k;i++)
if(a[i]>=n&&a[i]<=m)
cnt++;
cout<<m-n+1-cnt<<endl;
}
signed main()
{
//freopen("check.in","r",stdin);
//freopen("check.out","r",stdin);
ios::sync_with_stdio(false);cin.tie(nullptr);cout.tie(nullptr);
int T;
cin>>T;
while(T--)
{
solve();
}
return 0;
}
C - Trading(模拟)
#include <bits/stdc++.h>
#define bug cout << "***************" << endl
#define look(x) cout << #x << " -> " << x << endl
#define endl '\n'
#define int long long
#define YES cout << "YES" << endl;
#define NO cout << "NO" << endl;
using namespace std;
typedef pair<int, int> PII;
constexpr int N = 2e5 + 10 , INF = 2e9;
struct Node
{
int w;
int num;
}q[N];
int n;
bool cmp(Node a,Node b)
{
if(a.w==b.w) return a.num<b.num;
return a.w<b.w;
}
void solve()
{
cin>>n;
for(int i=0;i<n;i++)
{
cin>>q[i].w>>q[i].num;
}
sort(q,q+n,cmp);
int ans=0;
int l=0,r=n-1;
while(l<r)
{
// cout<<l<<' '<<r<<endl;
if(q[r].num>=q[l].num)
{
ans+=(q[r].w-q[l].w)*q[l].num;
q[r].num-=q[l].num;
l++;
}
else
{
ans+=(q[r].w-q[l].w)*q[r].num;
q[l].num-=q[r].num;
r--;
}
}
cout<<ans<<endl;
}
signed main()
{
//freopen("check.in","r",stdin);
//freopen("check.out","r",stdin);
ios::sync_with_stdio(false);cin.tie(nullptr);cout.tie(nullptr);
int T;
//T=1;
cin>>T;
while(T--)
{
solve();
}
return 0;
}
K - Peg Solitaire(搜索)
思路:
直接dfs 遇到棋子判断能够向四个方向跳跃 保存最小的值作为答案
棋盘状态需要回溯
#include <bits/stdc++.h>
#define bug cout << "***************" << endl
#define look(x) cout << #x << " -> " << x << endl
#define endl '\n'
#define int long long
#define YES cout << "YES" << endl;
#define NO cout << "NO" << endl;
using namespace std;
typedef pair<int, int> PII;
constexpr int N = 2e5 + 10 , INF = 2e9;
int n,m,k;
int g[10][10];
int ans;
void dfs(int now)
{
ans=min(ans,now);
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
if(g[i][j])
{
//向上跳
if(i>=3)
{
if(g[i-1][j]&&!g[i-2][j])
{
g[i][j]=g[i-1][j]=0;
g[i-2][j]=1;
dfs(now-1);
g[i][j]=g[i-1][j]=1;
g[i-2][j]=0;
}
}
//向下跳
if(i<=n-2)
{
if(g[i+1][j]&&!g[i+2][j])
{
g[i][j]=g[i+1][j]=0;
g[i+2][j]=1;
dfs(now-1);
g[i][j]=g[i+1][j]=1;
g[i+2][j]=0;
}
}
if(j>=3)
{
if(g[i][j-1]&&!g[i][j-2])
{
g[i][j]=g[i][j-1]=0;
g[i][j-2]=1;
dfs(now-1);
g[i][j]=g[i][j-1]=1;
g[i][j-2]=0;
}
}
if(j<=m-2)
{
if(g[i][j+1]&&!g[i][j+2])
{
g[i][j]=g[i][j+1]=0;
g[i][j+2]=1;
dfs(now-1);
g[i][j]=g[i][j+1]=1;
g[i][j+2]=0;
}
}
}
}
}
}
void solve()
{
memset(g,0,sizeof g);
cin>>n>>m>>k;
for(int i=0;i<k;i++)
{
int a,b;
cin>>a>>b;
g[a][b]=1;
}
ans=k;
dfs(k);
cout<<ans<<endl;
}
signed main()
{
//freopen("check.in","r",stdin);
//freopen("check.out","r",stdin);
ios::sync_with_stdio(false);cin.tie(nullptr);cout.tie(nullptr);
int T;
//T=1;
cin>>T;
while(T--)
{
solve();
}
return 0;
}
I - Path Planning(二分)
思路:
如果答案为x那么路径的序列一定存在0,1,2...x-1 具有二分性,考虑二分答案
因为路径中一定存在0,1,2,...x-1所以检查这些数的坐标 看能不能走到n,m
另一个思路:逐行逐列扫描 如果该数<x也就是说该位置必须走到 因为是按顺序扫描的且只能走右边和下边
所以后面要走的位置的列数一定大于等于当前最后一列 如果不行说明该路径不存在
#include <bits/stdc++.h>
#define bug cout << "***************" << endl
#define look(x) cout << #x << " -> " << x << endl
#define endl '\n'
#define int long long
#define YES cout << "YES" << endl;
#define NO cout << "NO" << endl;
using namespace std;
typedef pair<int, int> PII;
constexpr int N = 1e6 + 10 , INF = 2e9;
int n,m;
int g[N];
bool check(int x)
{
int last=0;
for(int i=0;i<n;i++)
for(int j=0;j<m;j++)
{
if(g[i*m+j]<x)
{
if(last>j)
return false;
last=j;
}
}
return true;
}
void solve()
{
cin>>n>>m;
for(int i=0;i<n;i++)
for(int j=0;j<m;j++)
cin>>g[i*m+j];
int l=0,r=n*m;
while(l<r)
{
int mid=(l+r+1)>>1;
if(check(mid)) l=mid;
else r=mid-1;
}
cout<<r<<endl;
}
signed main()
{
//freopen("check.in","r",stdin);
//freopen("check.out","r",stdin);
ios::sync_with_stdio(false);cin.tie(nullptr);cout.tie(nullptr);
int T;
//T=1;
cin>>T;
while(T--)
{
solve();
}
return 0;
}
D - New Houses(贪心)
思路:
最终一定有k个人有邻居 n-k个没有邻居
k的范围是[2,n]
也就是说挑k个ai并且n-k个bi
如果第i个人对答案的贡献是bi,而他挑ai使答案更优的情况一定使ai>bi
所以k个人如何挑选 ai-bi 从大到小排序 选前k个大的人
同时 k个人有邻居而n-k个没有邻居需要的房子数至少是k+2(n-k)=2n-k;
所以答案在k=2,3,...n中取最大值就可以
注意如果我们一开始求出所有bi的和然后每次取ai则可以O(1)求解出每次的答案
#include <bits/stdc++.h>
#define bug cout << "***************" << endl
#define look(x) cout << #x << " -> " << x << endl
#define endl '\n'
#define int long long
#define YES cout << "YES" << endl;
#define NO cout << "NO" << endl;
using namespace std;
typedef pair<int, int> PII;
constexpr int N = 2e5 + 10 , INF = 2e9;
int n,m;
int a[N],b[N];
void solve()
{
cin>>n>>m;
vector<int> vi;
int sum=0;
for(int i=1;i<=n;i++)
{
cin>>a[i]>>b[i];
vi.push_back(a[i]-b[i]);
sum+=b[i];
}
sort(vi.begin(),vi.end());
int ans=0;
if(m>=2*n-1) ans=sum;
sum+=vi[n-1];
for(int k=2;k<=n;k++)
{
sum+=vi[n-k];
if(m>=2*n-k) ans=max(ans,sum);
}
cout<<ans<<endl;
}
signed main()
{
//freopen("check.in","r",stdin);
//freopen("check.out","r",stdin);
ios::sync_with_stdio(false);cin.tie(nullptr);cout.tie(nullptr);
int T;
//T=1;
cin>>T;
while(T--)
{
solve();
}
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话