目录
以下代码均使用 cpp 1 编写。
D [CSP-J 2023] 公路
今年(2023年)CSP-J T2,贪心。
- 贪心思想:
- 找到一个比当前选定更优的、在选定的右边的站点,在那里停下加油。
代码:
#include<bits/stdc++.h>
#define debug false //debug作为调试开关
#define int long long
using namespace std;
int n,d,v[100005],a[100005],ans,b,c;
double s;
signed main()
{
ios::sync_with_stdio(0);
cin.tie(0), cout.tie(0);
cin>>n>>d;
if(n==1)
{
cout<<0;
return 0;
}
for(int i=1;i<n;i++)
cin>>v[i];
for(int i=1;i<=n;i++)
cin>>a[i];
b=v[1],c=1,s=0;
for(int i=2;i<n;i++)
{
if(a[c]>a[i])
{
if(s<(1.00*b/d))
{
ans+=ceil(1.00*b/d-s)*a[c];
#if debug
cout<<ans<<'\n';
#endif
s=ceil(1.00*b/d-s)-(1.00*b/d-s);
c=i;
b=0;
}
else
{
s-=(1.00*b/d);
b=0;
c=i;
}
}
b+=v[i];
}
if(s<(1.00*b/d))
ans+=ceil(1.00*b/d-s)*a[c];
cout<<ans;
return 0;
}
E 修复公路
可以使用并查集+二分/最小生成树。(比赛时用二分,忘记特判)
代码:
#include<bits/stdc++.h>
#define debug false
#define int long long
using namespace std;
int n,m,fa[1005];
struct node{
int x,y,t;
}a[100005];
bool cmp(node x,node y)
{
return x.t<=y.t;
}
int find(int x)
{
if(fa[x]==x)
return x;
return fa[x]=find(fa[x]);
}
void unionn(int x,int y)
{
x=find(x);
y=find(y);
if(x!=y)
fa[x]=y;
return;
}
bool check(int mid)
{
for(int i=1;i<=n;i++)
fa[i]=i;
for(int i=1;i<=m;i++)
if(a[i].t<=mid)
unionn(a[i].x,a[i].y);
else
break;
int f=find(1);
for(int i=2;i<=n;i++)
if(f!=find(i))
return false;
return true;
}
signed main()
{
ios::sync_with_stdio(0);
cin.tie(0), cout.tie(0);
cin>>n>>m;
for(int i=1;i<=m;i++)
cin>>a[i].x>>a[i].y>>a[i].t;
sort(a+1,a+1+m,cmp);
int l=0,r=100001;
while(l+1<r)
{
int mid=(l+r)/2;
if(check(mid))
r=mid;
else
l=mid;
}
if(!check(r))
{
cout<<-1;
return 0;
}
cout<<r;
return 0;
}
F 炸铁路
只会写暴力,暴力不会超时。 (暴力+并查集 好写一些)
代码:
#include<bits/stdc++.h>
#define debug false
#define int long long
using namespace std;
int n,m,fa[155];
struct node{
int x,y;
}a[5005];
int find(int x)
{
if(fa[x]==x)
return x;
return fa[x]=find(fa[x]);
}
void unionn(int x,int y)
{
x=find(x);
y=find(y);
if(x!=y)
fa[x]=y;
return;
}
bool check(int mid)
{
for(int i=1;i<=n;i++)
fa[i]=i;
for(int i=1;i<=m;i++)
if(i!=mid)
unionn(a[i].x,a[i].y);
int f=find(1);
for(int i=2;i<=n;i++)
if(f!=find(i))
return true;
return false;
}
bool cmp(node x,node y)
{
if(x.x!=y.x)
return x.x<y.x;
return x.y<y.y;
}
signed main()
{
ios::sync_with_stdio(0);
cin.tie(0), cout.tie(0);
cin>>n>>m;
for(int i=1;i<=m;i++)
{
cin>>a[i].x>>a[i].y;
if(a[i].x>a[i].y)
swap(a[i].x,a[i].y);
}
sort(a+1,a+1+m,cmp);
for(int i=1;i<=m;i++)
if(check(i))
cout<<a[i].x<<" "<<a[i].y<<"\n";
return 0;
}
作业题
G 集合
题目描述
Caima 给你了所有 [ a , b ] [a,b] [a,b] 范围内的整数。一开始每个整数都属于各自的集合。每次你需要选择两个属于不同集合的整数,如果这两个整数拥有大于等于 p p p 的 公共质因数 ,那么把它们所在的集合合并。
重复如上操作,直到没有可以合并的集合为止。
现在 Caima 想知道,最后有多少个集合。
答案
并查集+素数筛(我用的是欧拉筛)。
代码:
#include<bits/stdc++.h>
#define debug false
#define int long long
using namespace std;
int a, b, fa[100005], ans, p, c[100005], cnt;
bool vis[100005];
void init()
{
for (int i = 2; i <= b; i++)
vis[i] = true;
for (int i = 2; i <= b; i++)
{
if (vis[i])
c[++cnt] = i;
for (int j = 1; j <= cnt; j++)
{
if (i * c[j] > b)
break;
vis[i * c[j]] = false;
if (i % c[j] == 0)
break;
}
}
return;
}
int find(int x)
{
if (fa[x] == x)
return x;
return fa[x] = find(fa[x]);
}
void unionn(int x, int y)
{
x = find(x);
y = find(y);
if (x != y)
{
fa[x] = y;
}
return;
}
signed main()
{
ios::sync_with_stdio(0);
cin.tie(0), cout.tie(0);
cin >> a >> b >> p;
init();
for (int i = 1; i <= b; i++)
fa[i] = i;
for (int i = p; i <= b; i++)
if (vis[i])
for (int j = i * 2; j <= b; j += i)
{
unionn(i, j);
#if debug
cout << i << " " << j << " i j\n";
#endif
}
for (int i = a; i <= b; i++)
if (fa[i] == i)
{
ans++;
#if debug
cout << i << '\n';
#endif
}
#if debug
else
{
cout << "fa:" << find(i) << " i:" << i << "\n";
}
#endif
cout << ans;
return 0;
}
H 村村通
本人使用并查集+最小生成树。
代码:
#include<bits/stdc++.h>
#define debug false
#define int long long
using namespace std;
int n, m, fa[1005],cnt;
int find(int x)
{
if (fa[x] == x)
return x;
return fa[x] = find(fa[x]);
}
void unionn(int x, int y)
{
x = find(x);
y = find(y);
if (x != y)
fa[x] = y, cnt++;
return;
}
signed main()
{
ios::sync_with_stdio(0);
cin.tie(0), cout.tie(0);
cin >> n;
while (n != 0)
{
cin >> m;
for (int i = 1; i <= n; i++)
fa[i] = i;
cnt = 0;
int x, y;
for (int i = 1; i <= m; i++)
cin >> x >> y, unionn(x, y);
cout << n - 1 - cnt << '\n';
cin >> n;
}
return 0;
}
C++(c plus plus)是一种计算机高级程序设计语言,由C语言扩展升级而产生,最早于1979年由本贾尼·斯特劳斯特卢普在AT&T贝尔工作室研发。
C++既可以进行C语言的过程化程序设计,又可以进行以抽象数据类型为特点的基于对象的程序设计,还可以进行以继承和多态为特点的面向对象的程序设计。C++擅长面向对象程序设计的同时,还可以进行基于过程的程序设计。 C++几乎可以创建任何类型的程序:游戏、设备驱动程序、HPC、云、桌面、嵌入式和移动应用等。 甚至用于其他编程语言的库和编译器也使用C++编写。
C++拥有计算机运行的实用性特征,同时还致力于提高大规模程序的编程质量与程序设计语言的问题描述能力。 ——百度百科 ↩︎