Toyota Programming Contest 2024#7(AtCoder Beginner Contest 362)
⚪题和板题大赛/jk
好像能切的样子,但是太菜了,唐了 8 罚。
输出除去某个颜色以外,其他颜色代表的最大值。
点击查看代码
#include<bits/stdc++.h>
using namespace std;
int a,b,c;
string s;
signed main(){
cin>>a>>b>>c;
cin>>s;
if(s[0]=='R') a=1033;
else if(s[0]=='G') b=1033;
else c=1033;
cout<<min(a,min(b,c));
return 0;
}
给出三个点的坐标,判断该△是不是Rt。
勾股定理。Y1,又踩一次坑。
点击查看代码
#include<bits/stdc++.h>
using namespace std;
int x1,x2,x3,Y1,y2,y3;
int a[100];
int dis(int x1,int Y1,int x2,int y2){
return (x1-x2)*(x1-x2)+(Y1-y2)*(Y1-y2);
}
signed main(){
cin>>x1>>Y1>>x2>>y2>>x3>>y3;
a[0]=dis(x1,Y1,x2,y2),a[1]=dis(x1,Y1,x3,y3),a[2]=dis(x2,y2,x3,y3);
// sort(a,a+2);
if(a[0]+a[1]==a[2]||a[1]+a[2]==a[0]||a[2]+a[0]==a[1]) cout<<"Yes";
else cout<<"No";
return 0;
}
数列 \(a\) 满足 \(a_i\in[L_i,R_i]\),构造一组 \(a\),使得 \(\sum a_i=0\),或报告无解。
考虑贪心,若 \(l=\sum L_i>0\) 或 \(r=\sum R_i<0\) 显然无解。
否则继续操作,贪心地向 \(0\) 靠近:
- 若 \(r\ge R_i-L_i\),显然即使将 \(a_i\) 设为 \(L_i\),\(r\) 也大于等于 \(0\),一定是不劣的。
- 否则,将 \(a_i\) 设为 \(R_i-r\) 即可将当前序列和变成 \(\sum\limits_{i+1\sim r}R_i\),以后的 \(a_i\) 全为 \(R_i\) 即可。
点击查看代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int maxn=2e5+3;
int n,l[maxn],r[maxn],sl,sr;
signed main(){
cin>>n;
for(int i=1;i<=n;i++){
cin>>l[i]>>r[i];
sl+=l[i],sr+=r[i];
}
if(sl>0||sr<0){
cout<<"No";
return 0;
}
cout<<"Yes\n";
for(int i=1;i<=n;i++){
if(sr==0){ cout<<r[i]<<' ';}
else if(sr-(r[i]-l[i])>=0){
cout<<l[i]<<' ';
sr-=(r[i]-l[i]);
}else{
cout<<r[i]-sr<<' '; sr=0;
}
}
return 0;
}
给你简单无向图,点有点权,边有边权,求 \(1\) 为源点的最短路。
板子。松弛的时候把点权加进去就行了。
点击查看代码
#include<iostream>
#include<vector>
#include<queue>
using namespace std;
#define int long long
const int maxn=6e5+3;
const int maxm=4e5+3;
const int inf =0x3f3f3f3f3f3f3f3f;
struct edge{
int v,w;
edge(int v=0,int w=0): v(v),w(w){}
};
vector<edge>e[maxn];
#define pb emplace_back
int n,m,s,a[maxn],vis[maxn];
struct di{
int id,dis;
di(int id=0,int dis=0): id(id),dis(dis){}
bool operator<(const di o)const{return dis>o.dis;}
};
priority_queue<di>q;
int dis[maxn];
void dijkstra(){
for(int i=1;i<=m+n*2;i++)
dis[i]=inf;
q.push(di(s,dis[s]=a[s]));
while(!q.empty()){
di u=q.top();
q.pop();
if(!vis[u.id]){
vis[u.id]=1;
for(edge v:e[u.id]){
if(dis[v.v]>dis[u.id]+v.w+a[v.v]){
q.push(di(v.v,dis[v.v]=dis[u.id]+v.w+a[v.v]));
}
}
}
}
for(int i=2;i<=n;i++){
cout<<dis[i]<<' ';
}
}
signed main(){
cin>>n>>m;s=1;
for(int i=1;i<=n;i++) cin>>a[i];
for(int i=1,u,v,w;i<=m;i++){
cin>>u>>v>>w;
e[u].pb(edge(v,w));
e[v].pb(edge(u,w));
}
dijkstra();
return 0;
}
E - Count Arithmetic Subsequences
给你一个数列 \(a\),对于 \(\forall i\in[1,n]\) 求长度为 \(i\) 的等差子序列个数。
\(n\le 80,a_i\le 10^9\)
虚空写 DP 传奇(
DP 比较明显,设 \(f_{d,i,k}\) 表示公差为 \(d\),以 \(i\) 为结尾的,长度为 \(k\) 的等差数列数量,则有转移:
如果每次清空数组,就可以把 \(d\) 一维消去。在枚举过程中累加答案。但是枚举 \(d\) 的时间复杂度巨大,不可通过。
真的吗?
由于 \(n\le 80\),则差的数量上界为 \(\frac{n(n-1)}{2}<320\),所以我们可以把差存起来,直接从里面枚举,而不是枚举值域,最后时间复杂度 \(O(n^4)\)。
点击查看代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int mod=998244353;
int n,a[888],b[888],del[88888],tot,f[888][888],g[888];
int ggg[87888],top;
signed main(){
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i];
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
ggg[++top]=a[i]-a[j];
}
}
sort(ggg+1,ggg+top+1);
int tot=unique(ggg+1,ggg+top+1)-ggg-1;
for(int i=1;i<=n;i++) f[i][1]=1;
for(int div=1;div<=tot;div++){
for(int i=1;i<=n;i++){
for(int k=2;k<=i;k++)
for(int j=1;j<i;j++){
if(a[i]-a[j]==ggg[div])
f[i][k]=(f[i][k]+f[j][k-1])%mod;
}
}
for(int i=1;i<=n;i++)
for(int k=2;k<=i;k++){
g[k]=(g[k]+f[i][k])%mod;
f[i][k]=0;
}
}
cout<<n<<' ';
for(int i=2;i<=n;i++) cout<<g[i]<<' ';
return 0;
}
F - Perfect Matching on a Tree
给你一棵树,构造方案两两匹配点使得所有匹配点的距离和最大。
看懂了,大概是树形 DP 找重心,以重心为根,然后构造的话就在不同子树内找点连边即得最大,贪心是对的。
时间复杂度 \(O(n)\),有个技巧是先把同一子树内的点排在一起,考虑到重心的性质,每个子树大小不超过 \(\left\lfloor\frac{n}{2}\right\rfloor\),所以将 \(i\) 和 \(i+\left\lfloor\frac{n}{2}\right\rfloor\) 匹配,就能保证这两点不在同一子树内。
点击查看代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int maxn=2e5+3;
vector<int>e[maxn];
int n,siz[maxn],rt,f[maxn],ans=0x3f3f3f3f3f3f3f3f,dfn[maxn],dfncnt=-1;
void dfs(int u,int fa,int dep){
siz[u]=1;
for(int v:e[u]){
if(v!=fa){
dfs(v,u,dep+1);
siz[u]+=siz[v];
}
}
f[1]+=dep;
}
void dfs1(int u,int fa){
for(int v:e[u]){
if(v!=fa){
f[v]=f[u]+siz[1]-2*siz[v];
dfs1 (v,u);
}
}
if(ans>f[u]){
ans=f[u];
rt=u;
}
}
void dfs2(int u,int fa,int dep){
dfn[++dfncnt]=u;
siz[u]=dep;
for(int v:e[u]){
if(v!=fa) dfs2(v,u,dep+1);
}
}
signed main(){
cin>>n;
for(int i=1,u,v;i<n;i++){
cin>>u>>v;
e[u].emplace_back(v);
e[v].emplace_back(u);
}
dfs(1,0,0);
dfs1(1,0);
dfs2(rt,0,0); dfn[++dfncnt]=rt;
for(int i=1;i<=n/2;i++){
cout<<dfn[i]<<' '<<dfn[i+n/2]<<'\n';
}
return 0;
}
AC 自动机板题,甚至只要改输入(
绷不住了
点击查看代码
#include<bits/stdc++.h>
using namespace std;
const int maxn=5e5+3;
const int maxs=5e5+3;
int n,node,cnt;
char s[maxs],t[maxs];
int trie[maxn][30];
int fail[maxs],word[maxn],sum[maxs],in[maxs];
void insert(){
int u=0;
for(int i=0;s[i];i++){
if(!trie[u][s[i]-'a'])
trie[u][s[i]-'a']=++node;
u=trie[u][s[i]-'a'];
}
word[++cnt]=u;
}
queue<int>q;
void Fail(){
for(int i=0;i<26;i++) if(trie[0][i]) q.push(trie[0][i]);
while(!q.empty()){
int u=q.front();
q.pop();
for(int i=0;i<26;i++){
if(trie[u][i])
q.push(trie[u][i]),fail[trie[u][i]]=trie[fail[u]][i];
else trie[u][i]=trie[fail[u]][i];
}
}
for(int i=0;i<=node;i++) in[fail[i]]++;
}
void query(){
int u=0;
for(int i=0;t[i];i++){
u=trie[u][t[i]-'a'];
sum[u]++;
}
}
void topo(){
for(int i=0;i<=node;i++) if(!in[i]) q.push(i);
while(!q.empty()){
int u=q.front();
q.pop();
sum[fail[u]]+=sum[u];
if(!--in[fail[u]])
q.push(fail[u]);
}
}
signed main(){
cin>>t; cin>>n;
for(int i=0;i<n;i++) cin>>s, insert();
Fail(); query(); topo();
for(int i=1;i<=n;i++) cout<<sum[word[i]]<<'\n';
return 0;
}