(AtCoder Beginner Contest 312)
(AtCoder Beginner Contest 312)
#include<bits/stdc++.h> using namespace std; #define int long long //#define int __int128 typedef pair<int,int>PII; typedef pair<string,int>PSI; typedef pair<string,string>PSS; const int N=2e5+5,INF=0x3f3f3f3f,Mod=1e9+7; const double eps=1e-6; void solve(){ string s;cin>>s; string a[7]={"ACE","BDF","CEG","DFA","EGB","FAC","GBD"}; for(int i=0;i<7;++i){ if(s==a[i]){ cout<<"Yes";return ; } } cout<<"No"; } signed main(){ ios::sync_with_stdio(0),cin.tie(0),cout.tie(0); int t=1; //init(); //cin>>t; while(t--){ solve(); } return 0; }
思路:维护黑色的前缀和,枚举每个点,满足左上角和右下角的3、4个宽度的黑色个数都为9则输出
#include<bits/stdc++.h> using namespace std; #define int long long //#define int __int128 typedef pair<int,int>PII; typedef pair<string,int>PSI; typedef pair<string,string>PSS; const int N=2e5+5,INF=0x3f3f3f3f,Mod=1e9+7; const double eps=1e-6; int g[105][105]; void solve(){ int n,m;cin>>n>>m; for(int i=1;i<=n;++i) for(int j=1;j<=m;++j){ char c;cin>>c; if(c=='#')g[i][j]=1; g[i][j]+=(g[i-1][j]+g[i][j-1]-g[i-1][j-1]); } for(int i=1;i+8<=n;++i) for(int j=1;j+8<=m;++j){ int x1=i+2,y1=j+2,a1,a2,b1,b2; a1=g[x1][y1]-g[i-1][y1]-g[x1][j-1]+g[i-1][j-1]; x1=i+3,y1=j+3; a2=g[x1][y1]-g[i-1][y1]-g[x1][j-1]+g[i-1][j-1]; x1=i+5,y1=j+5; int x2=i+8,y2=j+8; b1=g[x2][y2]-g[x1-1][y2]-g[x2][y1-1]+g[x1-1][y1-1]; x1=i+6,y1=j+6; b2=g[x2][y2]-g[x1-1][y2]-g[x2][y1-1]+g[x1-1][y1-1]; //if(i==1&&j==10)cout<<a1<<' '<<a2<<' '<<b1<<' '<<b2<<'\n'; if(a1==a2&&a2==b1&&b1==b2&&b2==9){ cout<<i<<' '<<j<<'\n'; } } } signed main(){ ios::sync_with_stdio(0),cin.tie(0),cout.tie(0); int t=1; //init(); //cin>>t; while(t--){ solve(); } return 0; }
思路:对a、b排序,二分x,比较a中小于等于x的个数和b中大于等于x的个数,找出最小的x
#include<bits/stdc++.h> using namespace std; #define int long long //#define int __int128 typedef pair<int,int>PII; typedef pair<string,int>PSI; typedef pair<string,string>PSS; const int N=2e5+5,INF=0x3f3f3f3f,Mod=1e9+7; const double eps=1e-6; void solve(){ int n,m;cin>>n>>m; vector<int>a(n),b(m); for(int i=0;i<n;++i)cin>>a[i]; for(int i=0;i<m;++i)cin>>b[i]; sort(a.begin(),a.end()),sort(b.begin(),b.end()); int l=1,r=1e9+1,ans; auto check=[&](int x){ int p1= upper_bound(a.begin(),a.end(),x)-a.begin(); int p2= lower_bound(b.begin(),b.end(),x)-b.begin(); p2=b.size()-p2; return p1>=p2; }; while(l<=r){ int mid=l+r>>1; if(check(mid))ans=mid,r=mid-1; else l=mid+1; } cout<<ans; } signed main(){ ios::sync_with_stdio(0),cin.tie(0),cout.tie(0); int t=1; //init(); //cin>>t; while(t--){ solve(); } return 0; }
思路:对于 ‘( ’计一分,‘ )’计-1分;
dp[i][j]表示前i个字符的情况,且第i个字符选定后,当前的分值为j的情况数
枚举到i时,最多有i分,再枚举0~i分的情况;
那么当s[i]='('时,dp[i][j]=dp[i-1][j-1]
当s[i]=')'时,dp[i][j]=dp[i-1][j+1]
当s[i]='?'时,s[i]可以是'('和')',则dp[i][j]=dp[i][j+1]+dp[i][j-1]
最后的答案即为dp[n][0]
#include<bits/stdc++.h> using namespace std; #define int long long //#define int __int128 typedef pair<int,int>PII; typedef pair<string,int>PSI; typedef pair<string,string>PSS; const int N=3e3+5,INF=0x3f3f3f3f,Mod=1e9+7,mod=998244353; const double eps=1e-6; int dp[N][N]; void solve(){ string s; cin>>s;int n=s.size(); s.insert(0," "); dp[0][0]=1; for(int i=1;i<=n;++i){ for(int j=0;j<=i;++j){ if(s[i]=='('&&j-1>=0)dp[i][j]=dp[i-1][j-1]%mod; if(s[i]==')'&&j+1<=n)dp[i][j]=dp[i-1][j+1]%mod; if(s[i]=='?'){ if(j-1>=0)dp[i][j]=(dp[i][j]+dp[i-1][j-1])%mod; if(j+1<=n)dp[i][j]=(dp[i][j]+dp[i-1][j+1])%mod; } } } cout<<dp[n][0]; } signed main(){ ios::sync_with_stdio(0),cin.tie(0),cout.tie(0); int t=1; //init(); //cin>>t; while(t--){ solve(); } return 0; }
思路:坐标数据范围为0~100,且没有立方体重叠,用一个三维数组记录每个立方体,每个单位方块由左上角标记;
若两个立方体共面,可以在平行于xoy、xoz、yoz三个面中的一个面上共面,分别为z、y、x相等时;
那么枚举每个点,若点为立方体的最外层中的点,判断将该点平移到相邻面上后是否为其他立方体最外层中的点,是说明这两个立方体共面,用set存下来;
#include<bits/stdc++.h> using namespace std; #define int long long //#define int __int128 typedef pair<int,int>PII; typedef pair<string,int>PSI; typedef pair<string,string>PSS; const int N=100+5,INF=0x3f3f3f3f,Mod=1e9+7,mod=998244353; const double eps=1e-6; int g[N][N][N]; void solve(){ int n;cin>>n; for(int i=0,x1,y1,z1,x2,y2,z2;i<n;++i){ cin>>x1>>y1>>z1>>x2>>y2>>z2; for(int j1=x1;j1<x2;++j1) for(int j2=y1;j2<y2;++j2) for(int j3=z1;j3<z2;++j3) g[j1][j2][j3]=i+1; } vector<set<int>>ans(n+1); auto add=[&](int a,int b){ ans[a].insert(b); ans[b].insert(a); }; for(int i=0;i<100;++i) for(int j=0;j<100;++j) for(int k=0;k<100;++k){ if(g[i][j][k]){ if(g[i+1][j][k]&&g[i+1][j][k]!=g[i][j][k])add(g[i][j][k],g[i+1][j][k]); if(g[i][j+1][k]&&g[i][j+1][k]!=g[i][j][k])add(g[i][j][k],g[i][j+1][k]); if(g[i][j][k+1]&&g[i][j][k+1]!=g[i][j][k])add(g[i][j][k],g[i][j][k+1]); } } for(int i=1;i<=n;++i)cout<<ans[i].size()<<'\n'; } signed main(){ ios::sync_with_stdio(0),cin.tie(0),cout.tie(0); int t=1; //init(); //cin>>t; while(t--){ solve(); } return 0; }
思路:对拉环罐头、普通罐头、开罐器进行选择,要让幸福最大,应该优先选择幸福度大的拉环罐头、普通罐头、开罐数大的开罐器,对他们排序就好;
方法一:枚举选择拉环罐头的个数,二分求出选择普通罐头的最大数量,取所有可能的最大幸福
方法二:贪心的想,枚举选择的拉环罐头个数后,而后优先选择幸福度大的普通罐头,若当前的开罐数不够,则先选择一个开罐数最大的开罐器;可以求出所有选择数下,普通罐头带来的最大幸福度
#include<bits/stdc++.h> using namespace std; #define int long long //#define int __int128 typedef pair<int,int>PII; typedef pair<string,int>PSI; typedef pair<string,string>PSS; const int N=100+5,INF=0x3f3f3f3f,Mod=1e9+7,mod=998244353; const double eps=1e-6; void solve(){ int n,m;cin>>n>>m; vector<int>a(n+1),b(n+1),c(n+1); for(int i=1,t,x;i<=n;++i){ cin>>t>>x; if(t==0)a[i]=x; else if(t==1)b[i]=x; else c[i]=x; } sort(a.begin()+1,a.end(),greater<int>()); for(int i=1;i<=n;++i)a[i]+=a[i-1]; sort(b.begin()+1,b.end()); sort(c.begin()+1,c.end()); vector<int>last(n+1,0); int cnt=0; for(int i=1;i<=n;++i){ if(b.size()==1)last[i]=last[i-1]; else if(cnt==0){ if(c.size()!=1){ cnt+=c.back(); c.pop_back(); } last[i]=last[i-1]; }else{ cnt--; last[i]=last[i-1]+b.back(); b.pop_back(); } } int ans=0; for(int i=0;i<=m;++i)ans=max(ans,a[i]+last[m-i]); cout<<ans; } signed main(){ ios::sync_with_stdio(0),cin.tie(0),cout.tie(0); int t=1; //init(); //cin>>t; while(t--){ solve(); } return 0; }
#include<bits/stdc++.h> using namespace std; #define int long long //#define int __int128 typedef pair<int,int>PII; typedef pair<string,int>PSI; typedef pair<string,string>PSS; const int N=100+5,INF=0x3f3f3f3f,Mod=1e9+7,mod=998244353; const double eps=1e-6; void solve(){ int n,m;cin>>n>>m; vector<int>a,b,c; a.push_back(0),b.push_back(0),c.push_back(0); for(int i=1,t,x;i<=n;++i){ cin>>t>>x; if(t==0)a.push_back(x); else if(t==1)b.push_back(x); else c.push_back(x); } sort(a.begin()+1,a.end(),greater<int>()); sort(b.begin()+1,b.end(),greater<int>()); sort(c.begin()+1,c.end(),greater<int>()); for(int i=1;i<a.size();++i)a[i]+=a[i-1]; for(int i=1;i<b.size();++i)b[i]+=b[i-1]; for(int i=1;i<c.size();++i)c[i]+=c[i-1]; int A=a.size()-1,B=b.size()-1,C=c.size()-1; int ans=0; for(int i=0,l,r,mid,cnt;i<=min(m,A);++i){ l=0,r=min(m-i,B); while(l<=r){ mid=l+r>>1; if(c[min(C,m-i-mid)]>=mid)cnt=mid,l=mid+1; else r=mid-1; } ans=max(ans,a[i]+b[cnt]); } cout<<ans; } signed main(){ ios::sync_with_stdio(0),cin.tie(0),cout.tie(0); int t=1; //init(); //cin>>t; while(t--){ solve(); } return 0; }
思路:求不在一条路径的三个点(i,j,k)的数量;找出在一条路径上的(i,j,k)的数量s,C(n,3)-s即可;
求出以每个点为根的子树的节点数,含该点的路径有两种情况:还有两个点分别在不同的子树、还有两个点分别在子树和非子树上,统计所有的情况即可
#include<bits/stdc++.h> using namespace std; #define int long long //#define int __int128 typedef pair<int,int>PII; typedef pair<string,int>PSI; typedef pair<string,string>PSS; const int N=2e5+5,INF=0x3f3f3f3f,Mod=1e9+7,mod=998244353; const double eps=1e-6; vector<int>ve[N],g[N]; vector<int>cnt(N+1); void dfs(int u){ cnt[u]=1; for(auto v:ve[u]){ if(cnt[v])continue; g[u].push_back(v); dfs(v); cnt[u]+=cnt[v]; } } void solve(){ int n;cin>>n; for(int i=1,x,y;i<n;++i){ cin>>x>>y; ve[x].push_back(y),ve[y].push_back(x); } int ans=n*(n-1)*(n-2)/6; dfs(1); for(int i=1,c;i<=n;++i){ c=0; for(auto v:g[i])c+=cnt[v]*(cnt[i]-cnt[v]-1); c/=2; c+=(cnt[i]-1)*(n-cnt[i]); ans-=c; } cout<<ans; } signed main(){ ios::sync_with_stdio(0),cin.tie(0),cout.tie(0); int t=1; //init(); //cin>>t; while(t--){ solve(); } return 0; }