Educational Codeforces Round 3
A. USB Flash Drives
- 降序排序后,贪心,甚至不会爆longlong
void solve()
{
int n,m;
cin>>n>>m;
vector<int> a(n);
for(int i=0;i<n;i++)
cin>>a[i];
sort(all(a));reverse(all(a));
int s=0,ans=0;
for(int i=0;i<n;i++)
{
if(s>=m) break;
s+=a[i],ans++;
}
cout<<ans<<endl;
return;
}
B. The Best Gift
- 大意:有多少种互不相同不同的组合
- 用map记录这个类型出现的次数
- 一本书的贡献为 与这本书不同类型的数量
void solve()
{
int n,m;
cin>>n>>m;
LL ans=0,s=0;
vector<int> a(n);
map<int,int> mp;
for(int i=0;i<n;i++)
{
cin>>a[i];
mp[a[i]]++;
s++;
}
for(auto it:mp)
{
ans+=(it.se*(s-it.se));
}
cout<<ans/2ll<<endl;
return;
}
C. Load Balancing
-
大意:求让最大值和最小值的差最小的操作次数
-
对数组进行排序,使之升序
-
为所有数之和, 代表平均数, 代表余数
-
,
-
当 ,最大值和最小值的差为 ,答案即为
-
当 ,最大值和最小值的差为 ,答案即为
LL a[N],b[N];
void solve()
{
LL n;
cin>>n;
LL ans=0,s=0;
for(int i=1;i<=n;i++)
{
cin>>a[i];
s+=a[i];
}
sort(a+1,a+1+n);
LL k=s/n,r=s%n;
for(int i=1;i<=n;i++)
b[i]=k;
for(int i=n;i>=n-r+1;i--)
{
b[i]++;
}
for(int i=1;i<=n;i++)
ans+=max(a[i]-b[i],0ll);
cout<<ans<<endl;
return;
}
D. Gadgets for dollars and pounds
-
二分,前缀和,贪心
-
大意:在 天中买东西,每天有不同的汇率, 个商品,只能使用pounds或dollars,要买 个,但只有 元钱,判断能不能买,能输出哪天能买完,和哪一天买第几个商品
-
在 天中,若第 天能买完 个,那 第 天也能买完,也就是在 天中找到最小满足条件的 ,且第 天不能买完,这是有单调性的,所以我们二分哪天能买完
-
check中,在 天中找到最小pounds和dollars的汇率分别是 和 ,设消费为 。题目并没有限制每天购买商品的数量,我们等到汇率最小那天买完是最划算的贪心
-
这里就有一个问题,如何去确定换了前去买用pounds,还是用dollars的?
-
因为买 个商品,可以对pounds,和dollars进行排序,用前缀和处理
-
,运用前缀和就可以在的时间内处理出第 天结束的最小花销
-
剩下的输出方案,记录下最小花销下的 、 和 pounds和dollars 汇率最小的日子就很容易解决了
代码有点丑QAQ
const int N = 200010;
LL n,m,k,s,a[N],b[N];
int id,d1,d2;
LL cnt1=0,cnt2=0,s1[N],s2[N];
PII c1[N],c2[N];
bool check(LL x)
{
LL a1=1e18,b1=1e18;
for(int i=1;i<=x;i++)
{
if(a[i]<a1)
d1=i,a1=a[i];
if(b[i]<b1)
d2=i,b1=b[i];
}
LL sum=1e18;
for(int i=0;i<=k;i++)
{
if( !(i<=cnt1&&k-i<=cnt2)) continue;
LL t1=s1[i],t2=s2[k-i];
LL r1=t1*a1,r2=t2*b1;
if(r1+r2<sum)
sum=r1+r2,id=i;
}
if(sum<=s) return true;
else return false;
}
void solve()
{
cin>>n>>m>>k>>s;
for(int i=1;i<=n;i++)
cin>>a[i];
for(int i=1;i<=n;i++)
cin>>b[i];
for(int i=1;i<=m;i++)
{
LL t,cc; cin>>t>>cc;
if(t==1) c1[++cnt1].fi=cc,c1[cnt1].se=i;
else
c2[++cnt2].fi=cc,c2[cnt2].se=i;
}
sort(c1+1,c1+1+cnt1);
sort(c2+1,c2+1+cnt2);
for(int i=1;i<=cnt1;i++)
s1[i]=s1[i-1]+c1[i].fi;
for(int i=1;i<=cnt2;i++)
s2[i]=s2[i-1]+c2[i].fi;
if(check(n)==false)
{
cout<<-1<<endl; return;
}
int l=1,r=n;
while(l<r)
{
int mid=(l+r)>>1;
if(check(mid)) r=mid;
else l=mid+1;
}
if(check(l))
{
cout<<l<<endl;
vector<PII> ans;
int j=0;
for(int i=1;i<=id;i++)
ans.pb({d1,c1[++j].se});
j=0;
for(int i=id+1;i<=k;i++)
ans.pb({d2,c2[++j].se});
for(auto &it:ans)
cout<<it.se<<" "<<it.fi<<endl;
}
return;
}
Minimum spanning tree for each edge
给你 个点, 条边,如果对于一个最小生成树中要求必须包括第 条边,那么最小生成树的权值总和最小是多少。
我们若是在最小生成树的基础上再连一条边,也就是将 和 连边,这时候出现了一个环,我们考虑在这个环上面删去最大边权即可,可以用树上倍增解决
const int N = 2e5 + 10;
const int M = 2e5 + 10;
const int LOGN = 20;
int n, m, p[N], dep[N], fa[N][LOGN + 2];
ll g[N][LOGN + 2];
ll res;
array<ll, 3> e2[M];
vector<pair<ll, ll>> e[N];
struct Edge
{
ll u, v, w;
bool operator <(const Edge& W)const
{
return w < W.w;
}
}edge[M];
int find(int x)
{
if (p[x] != x) p[x] = find(p[x]);
return p[x];
}
void kruskal()
{
sort(edge + 1, edge + 1 + m);
for (int i = 1; i <= n; i++) p[i] = i;
// for (int i = 1; i <= m; i++)
// {
// ll u = edge[i].u, v = edge[i].v, w = edge[i].w;
// // cout<<u<<" "<<v<<" "<<w<<'\n';
// }
// cout<<'\n';
for (int i = 1; i <= m; i++)
{
ll u = edge[i].u, v = edge[i].v, w = edge[i].w;
// u = find(u), v = find(v);
// cout<<u<<" "<<v<<" "<<w<<'\n';
if (find(u) != find(v))
{
p[find(u)] = find(v);
res += w;
e[u].push_back({v, w});
e[v].push_back({u, w});
}
}
}
void dfs(int u, int from)
{
dep[u] += dep[from] + 1;
for(auto [v, w] : e[u]) {
if(v == from) continue;
fa[v][0] = u;
g[v][0] = w;
dfs(v, u);
}
}
void lca_init()
{
for(int j = 1; j <= LOGN; j++)
for(int i = 1; i <= n; i++)
{
fa[i][j] = fa[fa[i][j - 1]][j - 1];
g[i][j] = max(g[i][j - 1], g[fa[i][j - 1]][j - 1]);
}
}
ll lca_query(int u, int v)
{
ll ret = 0;
if(dep[u] < dep[v]) swap(u, v);
int d = dep[u] - dep[v];
for(int j = LOGN; j >= 0; j--)
if(d & (1 << j))
ret = max(ret, g[u][j]), u = fa[u][j];
// cout<<u<<" "<<v<<" "<<dep[u]<<" "<<dep[v]<<" "<<ret<<'\n';
if(u == v) return ret;
for(int j = LOGN; j >= 0; j--)
if(fa[u][j] != fa[v][j])
{
ret = max({ret, g[u][j], g[v][j]});
// cout<<g[u][j]<<" "<<g[v][j]<<'\n';
u = fa[u][j], v = fa[v][j];
}
return max({g[u][0], g[v][0], ret});
}
void solve()
{
cin >> n >> m;
for (int i = 1; i <= m; i++)
{
int u, v, w; cin >> u >> v >> w;
edge[i] = {u, v, w};
e2[i] = {u, v, w};
}
kruskal();
// cout<<res<<'\n';
dfs(1, 0); lca_init();
for(int i = 1; i <= m; i++)
{
ll t = lca_query(e2[i][0], e2[i][1]);
cout<<res + e2[i][2] - t<<'\n';
// cout<<e2[i][0]<<" "<<e2[i][1]<<" "<<t<<'\n';
}
// cout<<"L : ";
// for(int i = 1; i <= n; i++)
// cout<<l[i]<<" ";
// cout<<'\n';
return;
}
本文来自博客园,作者:magicat,转载请注明原文链接:https://www.cnblogs.com/magicat/p/17070875.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)