CF1927 A~G
庆祝一下全写的正解。
赛时 1h A~E,罚坐 1h,以为 dfs 找环复杂度巨大导致没有 F。
A
找最左边和最右边的'B'即可,注意找不到时的处理。
#include<bits/stdc++.h> #define int long long template<typename T> void read(T &x){ int f=1; char c=getchar(); x=0; while(c<'0'||c>'9'){ if(c=='-') f=-1; c=getchar(); } while(c>='0'&&c<='9') x=x*10+(int)(c-'0'),c=getchar(); x*=f; } template<typename T,typename I> void chkmin(T &a,I b){ a=std::min(a,b); } template<typename T,typename I> void chkmax(T &a,T b){ a=std::max(a,b); } const int inf=1e18+10,MOD1=998244353,MOD2=1e9+7; signed main(){ int t; read(t); while(t--){ int n; read(n); int l,r; l=-1,r=-1; for(int i=1;i<=n;i++){ char c=getchar(); if(c=='B'){ if(l==-1) l=i,r=i; else r=i; } } printf("%lld\n",std::max(r-l+1,0ll)); } return 0; } /* -读入字符一定检查回车 - 能不能搜索? -函数要有返回值! -想好了再写! */
B
用
#include<bits/stdc++.h> #define int long long template<typename T> void read(T &x){ int f=1; char c=getchar(); x=0; while(c<'0'||c>'9'){ if(c=='-') f=-1; c=getchar(); } while(c>='0'&&c<='9') x=x*10+(int)(c-'0'),c=getchar(); x*=f; } template<typename T,typename I> void chkmin(T &a,I b){ a=std::min(a,b); } template<typename T,typename I> void chkmax(T &a,T b){ a=std::max(a,b); } const int inf=1e18+10,MOD1=998244353,MOD2=1e9+7; signed main(){ int t; read(t); while(t--){ int n; read(n); int t[30]={0}; for(int i=1;i<=n;i++){ int g; read(g); int flag=0; for(int j=1;j<=26;j++){ if(g==t[j]) { t[j]++; flag=j; break; } } printf("%c",(char)('a'+flag-1)); } printf("\n"); } return 0; } /* -读入字符一定检查回车 - 能不能搜索? -函数要有返回值! -想好了再写! */
C
明显的贪心,记录一下每个数字在哪个数组中出现过,统计一下每个数组有多少只在自己数组出现的数,如果这个数超过
读者自证不难。
#include<bits/stdc++.h> #define int long long template<typename T> void read(T &x){ int f=1; char c=getchar(); x=0; while(c<'0'||c>'9'){ if(c=='-') f=-1; c=getchar(); } while(c>='0'&&c<='9') x=x*10+(int)(c-'0'),c=getchar(); x*=f; } template<typename T,typename I> void chkmin(T &a,I b){ a=std::min(a,b); } template<typename T,typename I> void chkmax(T &a,T b){ a=std::max(a,b); } const int inf=1e18+10,MOD1=998244353,MOD2=1e9+7; const int maxn=4e5+10; int a[maxn],b[maxn],t1[maxn],t2[maxn]; struct node{ int fi,se,th; }; signed main(){ int t; read(t); while(t--){ int n,m,k; read(n),read(m),read(k); for(int i=1;i<=k;i++) t1[i]=t2[i]=0; for(int i=1;i<=n;i++) { read(a[i]); t1[a[i]]++; } for(int i=1;i<=m;i++) { read(b[i]); t2[b[i]]++; } int s1,s2; s1=s2=0; bool flag=1; for(int i=1;i<=k;i++){ // printf("&&%lld %lld %lld\n",i,t1[i],t2[i]); if(t1[i]&&t2[i]) continue; if(t1[i]) s1++; else if(t2[i]) s2++; else { flag=0; break; } if(s1>k/2||s2>k/2){ flag=0; break; } } if(flag) printf("YES\n"); else printf("NO\n"); } return 0; } /* -读入字符一定检查回车 - 能不能搜索? -函数要有返回值! -想好了再写! */
D
经典套路,维护一下每个数后面第一个和它不一样的数即可,这可以从后向前递推得到。
#include<bits/stdc++.h> #define int long long template<typename T> void read(T &x){ int f=1; char c=getchar(); x=0; while(c<'0'||c>'9'){ if(c=='-') f=-1; c=getchar(); } while(c>='0'&&c<='9') x=x*10+(int)(c-'0'),c=getchar(); x*=f; } template<typename T,typename I> void chkmin(T &a,I b){ a=std::min(a,b); } template<typename T,typename I> void chkmax(T &a,T b){ a=std::max(a,b); } const int inf=1e18+10,MOD1=998244353,MOD2=1e9+7; const int maxn=2e5+10; int a[maxn],to[maxn]; namespace bcj{ void init(int n){ for(int i=1;i<=n+1;i++) to[i]=i; } int fa(int p){ if(to[p]==p) return p; return to[p]=fa(to[p]); } } signed main(){ int t; read(t); while(t--){ int n; read(n); for(int i=1;i<=n;i++) read(a[i]); to[n]=n+1; for(int i=n-1;i>=1;i--){ if(a[i]==a[i+1]) to[i]=to[i+1]; else to[i]=i+1; } int q; read(q); while(q--){ int l,r; read(l),read(r); if(to[l]>r) printf("-1 -1\n"); else printf("%lld %lld\n",l,to[l]); } printf("\n"); } return 0; } /* -读入字符一定检查回车 - 能不能搜索? -函数要有返回值! -想好了再写! */
E
考虑一个长为
发现
根据数学归纳法,发现若
令
具体可以看代码实现。
#include<bits/stdc++.h> #define int long long template<typename T> void read(T &x){ int f=1; char c=getchar(); x=0; while(c<'0'||c>'9'){ if(c=='-') f=-1; c=getchar(); } while(c>='0'&&c<='9') x=x*10+(int)(c-'0'),c=getchar(); x*=f; } template<typename T,typename I> void chkmin(T &a,I b){ a=std::min(a,b); } template<typename T,typename I> void chkmax(T &a,T b){ a=std::max(a,b); } const int inf=1e18+10,MOD1=998244353,MOD2=1e9+7; const int maxn=2e5+10; int a[maxn]; signed main(){ int t; read(t); while(t--){ int n,k; read(n),read(k); int r=n+1,l=0,k_=k; if(k&1) k_=k+1; for(int i=1;i<=k;i++){ if(i&1) a[i]=--r; else a[i]=++l; int z=i+k_; while(z<=n){ if(i&1)a[z]=--r; else a[z]=++l; z+=k_; } } for(int i=1;i<=n;i++) printf("%lld ",a[i]); printf("\n"); } return 0; } /* -读入字符一定检查回车 - 能不能搜索? -函数要有返回值! -想好了再写! */
F
利用生成树的思想,从大到小往里面加边,如果发现成环,则更新最小答案(加边顺序使得新答案一定小于原来),即为答案。
至于寻找简单环,可以利用 dfs 来找环,注意实现的细节,一定要加上记忆化的技巧。
#include<bits/stdc++.h> #define int long long #define ok printf("ORz\n") template<typename T> void read(T &x){ int f=1; char c=getchar(); x=0; while(c<'0'||c>'9'){ if(c=='-') f=-1; c=getchar(); } while(c>='0'&&c<='9') x=x*10+(int)(c-'0'),c=getchar(); x*=f; } template<typename T,typename I> void chkmin(T &a,I b){ a=std::min(a,b); } template<typename T,typename I> void chkmax(T &a,T b){ a=std::max(a,b); } const int inf=1e18+10,MOD1=998244353,MOD2=1e9+7; const int maxm=4e5+10; struct node{ int nxt,to,v; }s[maxm]; int fi[maxm]; struct node2{ int u,v,w; }p[maxm]; int be=0,tot=0,t; bool cmp(node2 s1,node2 s2){ return s1.w>s2.w; } int to[maxm],minans; int go(int p){ if(to[p]==p) return p; return to[p]=go(to[p]); } struct node3{ int to,nxt,v; }p2[maxm]; int F[maxm]; int tot2; std::vector<int>ans[(int)1e4+10],mans; bool vis[maxm],mflag=1; void dfs(int now,int mb,bool flag){ if(!mflag) return ; // printf("@@@@@%lld\n",now); // if(now==mb&&flag){ // mans=ans; // mans.pop_back(); // return ; // } int zz=F[now]; while(zz){ if(!mflag) return ; int to=p2[zz].to,nxt=p2[zz].nxt; if(vis[to]) { if(to==mb&&ans[t].size()>2) { mflag=0; // ans[t].pop_back(); // mans=ans[t]; // printf("##%lld %lld\n",mans.size(),ans[t].size()); return ; } else { zz=nxt; continue; } } vis[to]=1,ans[t].push_back(to); dfs(to,mb,1); if(mflag) ans[t].pop_back(); zz=nxt; } return ; } signed main(){ // int t; read(t); while(t--){ int n,m; read(n),read(m); int tot=0; for(int i=1;i<=m;i++){ int u,v,w; read(u),read(v),read(w); p[i].u=u,p[i].v=v,p[i].w=w; } std::sort(p+1,p+m+1,cmp); int fi=-1,se,vv; int tot3=0; for(int i=1;i<=n;i++) F[i]=0,vis[i]=0,to[i]=i; for(int i=1;i<=m;i++){ int u=p[i].u,v=p[i].v,w=p[i].w; if(go(u)==go(v)) { fi=u,se=v,vv=w; } else to[go(u)]=go(v); } for(int i=1;i<=m;i++){ int u=p[i].u,v=p[i].v,w=p[i].w; tot3++; // F[u]=tot3; p2[tot3].to=v,p2[tot3].nxt=F[u],F[u]=tot3; tot3++; p2[tot3].to=u,p2[tot3].nxt=F[v],F[v]=tot3; } // for(int i=1;i<=n;i++) vis[i]=0; printf("%lld ",vv); // vis[fi]=1; minans=inf; // ans.shirnk_to_fit(); // std::vector<int>ans; ans[t].push_back(fi); vis[fi]=2; mflag=1; dfs(fi,fi,0); printf("%lld\n",ans[t].size()); for(int i:ans[t]) printf("%lld ",i); printf("\n"); } return 0; } /* -读入字符一定检查回车 - 能不能搜索? -函数要有返回值! -想好了再写! */
G
非常巧妙的一道区间 dp。
令
先说转移。这里尽量采用递推法。分别讨论第
可以证明,这样转移会得到正确答案,读者自证不难。
现在我们考虑,为什么不能设置状态为被染色的点中最左边和最右边的分别为
关于如何在考场上想到这个做法,或许要凭 OI 上的直觉了。
#include<bits/stdc++.h> #define int long long template<typename T> void read(T &x){ int f=1; char c=getchar(); x=0; while(c<'0'||c>'9'){ if(c=='-') f=-1; c=getchar(); } while(c>='0'&&c<='9') x=x*10+(int)(c-'0'),c=getchar(); x*=f; } template<typename T,typename I> void chkmin(T &a,I b){ a=std::min(a,b); } template<typename T,typename I> void chkmax(T &a,T b){ a=std::max(a,b); } const int inf=1e18+10,MOD1=998244353,MOD2=1e9+7; const int maxn=110; int a[maxn],dp[maxn][maxn][maxn],q[maxn],h[maxn]; signed main(){ int t; read(t); while(t--){ int n; read(n); for(int i=1;i<=n;i++) read(a[i]),q[i]=std::max(i-a[i]+1,1ll),h[i]=std::min(i+a[i]-1,n); memset(dp,0x3f,sizeof(dp)); dp[0][1][0]=0; for(int i=0;i<n;i++){ for(int j=1;j<=n+1;j++) for(int k=0;k<=n;k++) chkmin(dp[i+1][j][k],dp[i][j][k]); for(int j=1;j<=n+1;j++) for(int k=0;k<=n;k++){ if(q[i+1]<=j) chkmin(dp[i+1][std::max(k+1,i+2)][std::max(k,i+1)],dp[i][j][k]+1); else chkmin(dp[i+1][j][std::max(k,i+1)],dp[i][j][k]+1); } for(int j=1;j<=n+1;j++) for(int k=0;k<=n;k++){ if(j>=i+1) chkmin(dp[i+1][std::max(j,h[i+1]+1)][std::max(h[i+1],k)],dp[i][j][k]+1); else chkmin(dp[i+1][j][std::max(h[i+1],k)],dp[i][j][k]+1); } } printf("%lld\n",dp[n][n+1][n]); } return 0; } /* -读入字符一定检查回车 - 能不能搜索? -函数要有返回值! -想好了再写! */
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 在鹅厂做java开发是什么体验
· 百万级群聊的设计实践
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
· 永远不要相信用户的输入:从 SQL 注入攻防看输入验证的重要性
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析