A题 Angry Students
题目大意:
给你一个只包含A和P的字符串,求每个A字符后面连续出现P字符的最大次数。
举个例子:APAPPAPPP 答案为3,因为最后一个A后面出现连续出现了3个P字符,出现次数是最大的。
Input
3
12
APPAPPPAPPPP
3
AAP
3
PPAOutput
4
1
0
题解:直接维护一个记录A后面最大连续P出现次数的值就行了,注意特殊考虑一下没有出现A就出现P的情况。
代码实现:
#pragma GCC optimize(2) #include<iostream> #include<algorithm> #include<cmath> #include<cstring> #include<cstdio> #include<cstdlib> #include<vector> #include<map> #include<set> #include<stack> #include<queue> #define PI atan(1.0)*4 #define E 2.718281828 #define rp(i,s,t) for (register int i = (s); i <= (t); i++) #define RP(i,t,s) for (register int i = (t); i >= (s); i--) #define ll long long #define ull unsigned long long #define mst(a,b) memset(a,b,sizeof(a)) #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 #define pii pair<int,int> #define mp make_pair #define pb push_back #define debug printf("ac\n"); using namespace std; inline int read() { int a=0,b=1; char c=getchar(); while(c<'0'||c>'9') { if(c=='-') b=-1; c=getchar(); } while(c>='0'&&c<='9') { a=(a<<3)+(a<<1)+c-'0'; c=getchar(); } return a*b; } const int INF = 0x3f3f3f3f; string s; int main(){ int T=read(); while(T--){ int n=read(); cin>>s; int maxn=0,sum=-INF; rp(i,0,n-1){ if(s[i]=='A') maxn=max(maxn,sum),sum=0; else sum++; } maxn=max(sum,maxn); cout<<maxn<<endl; } return 0; }
B题 Hyperset
题目大意:
给你两个整数n和k,然后给你n个长度为k的字符串(只含有'S','E','T')。
在这n个字符串中任选3个字符串,如果这三个字符串满足以下条件:
1.把这3个字符串的第k个位置的字符可以组合成"SET"
2.或者这三个字符串的第k个位置的字符都相同
则这三个字符串对答案的贡献为1。
求这n个字符串中满足条件的个数。
Input
5 4
SETT
TEST
EEET
ESTE
STESOutput
2
Note
样例中符合条件的个数为2。分别是
1."SETT", "TEST", "EEET"
2."TEST", "ESTE", "STES"
题解:
这个题不要多想,能暴力就直接暴力,不过我们考虑枚举两个字符串,第三个字符串就定了,因此再用set找就行了。O(k*n^2*log(n))的时间复杂度可以过。
代码实现:
#pragma GCC optimize(2) #include<iostream> #include<algorithm> #include<cmath> #include<cstring> #include<cstdio> #include<cstdlib> #include<vector> #include<map> #include<set> #include<stack> #include<queue> #define PI atan(1.0)*4 #define E 2.718281828 #define rp(i,s,t) for (register int i = (s); i <= (t); i++) #define RP(i,t,s) for (register int i = (t); i >= (s); i--) #define ll long long #define ull unsigned long long #define mst(a,b) memset(a,b,sizeof(a)) #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 #define pii pair<int,int> #define mp make_pair #define pb push_back #define debug printf("ac\n"); using namespace std; inline int read() { int a=0,b=1; char c=getchar(); while(c<'0'||c>'9') { if(c=='-') b=-1; c=getchar(); } while(c>='0'&&c<='9') { a=(a<<3)+(a<<1)+c-'0'; c=getchar(); } return a*b; } const int INF = 0x3f3f3f3f; const int N = 1507; string s[N]; int cnt[10]; int n,K; set<string> ss; int main(){ n=read(),K=read(); rp(i,0,n-1) cin>>s[i],ss.insert(s[i]); // rp(i,0,n-1) cout<<s[i]<<endl; ll ans=0; rp(i,0,n-2){ rp(j,i+1,n-1){ string temp=""; rp(k,0,K-1){ if(s[i][k]==s[j][k]) temp+=s[i][k]; else{ if((s[i][k]=='S'&&s[j][k]=='E')||(s[i][k]=='E'&&s[j][k]=='S')) temp+="T"; if((s[i][k]=='S'&&s[j][k]=='T')||(s[i][k]=='T'&&s[j][k]=='S')) temp+="E"; if((s[i][k]=='T'&&s[j][k]=='E')||(s[i][k]=='E'&&s[j][k]=='T')) temp+="S"; } } if(ss.find(temp)!=ss.end()) ans++; } } cout<<ans/3<<endl; return 0; }
C题 Garland
题目大意:
首先定义一个排列的复杂度:满足排列中相邻位置的数,一个数为奇数,一个数为偶数的个数(即具有奇偶校验性)。
比如:1,4,2,3,5的复杂度为2,因为(1,4)和(2,3)满足条件。
然后给你n个数的一个排列,某些位置为0,表示该位置没有数。
因此你可以填补这个排列,但是要保证填补后排列的复杂度最小,求这个最小的排列复杂度。
Input
5
0 5 0 2 3Output
2
Note
样例中符合条件的排列是1,5,4,2,3,这样排列复杂度最小,且排列复杂度为2
题解:
本来想的是可以贪心一下来做,就是奇数的放一起,偶数的放一起。但是这样如果时1,0,0,0,5的话就没法考虑,因此要考虑一种可以考虑所有情况,然后取最优的算法,不难想到dfs,但是2^100,肯定也不行,因此我们可以考虑记忆话搜索+dp来做,因为n最大为100,不难想到可以推一个O(n^3)的dp,
虽然我没想到,还是dp做的少。首先定义状态为dp[i][o][e][k]表示考虑第i位数,当前奇数个数为o,偶数个数为e,k为1表示上一位为奇数,0表示上一位为偶数
状态转移方程:
当p[i]!=0时//当前位置有数
if(k==2&&p[i]%2==k) dp[i][o][e][k]=dp[i][o][e][p[i]%2] //位置为1时以及当前位的奇偶性和上一位相同
else dp[i][o][e][k]=dp[i][o][e][p[i]%2]+1 //当前位的奇偶性和上一位不同
当p[i]==0时//当前位置没有数
L为考虑填一个奇数的答案
R为考虑填一个偶数的答案
求L和R的时候需要考虑k==2,k==1,k==0的情况,考虑是否加1,即和上一位奇偶性是否相同
dp[i][o][e][k]=min(dp[i][o][e][k]+L,dp[i][o][e][k]+R)
思路大致清楚了,记忆话搜索一下就行了。
#pragma GCC optimize(2) #include<iostream> #include<algorithm> #include<cmath> #include<cstring> #include<cstdio> #include<cstdlib> #include<vector> #include<map> #include<set> #include<stack> #include<queue> #define PI atan(1.0)*4 #define E 2.718281828 #define rp(i,s,t) for (register int i = (s); i <= (t); i++) #define RP(i,t,s) for (register int i = (t); i >= (s); i--) #define ll long long #define ull unsigned long long #define mst(a,b) memset(a,b,sizeof(a)) #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 #define pii pair<int,int> #define mp make_pair #define pb push_back #define debug printf("ac\n"); using namespace std; inline int read() { int a=0,b=1; char c=getchar(); while(c<'0'||c>'9') { if(c=='-') b=-1; c=getchar(); } while(c>='0'&&c<='9') { a=(a<<3)+(a<<1)+c-'0'; c=getchar(); } return a*b; } const int INF = 0x3f3f3f3f; int p[105],visited[105]; vector<int> s1; vector<int> s2; int dp[105][105][105][2]; int n; int dfs(int i,int odd_num,int even_num,int k){ if(i==n+1) return 0; if(dp[i][odd_num][even_num][k]!=-1) return dp[i][odd_num][even_num][k]; dp[i][odd_num][even_num][k]=0; if(p[i]!=0){ if(k==2||p[i]%2==k) dp[i][odd_num][even_num][k]=dfs(i+1,odd_num,even_num,p[i]%2); else dp[i][odd_num][even_num][k]=dfs(i+1,odd_num,even_num,p[i]%2)+1; } else{ int l=1005,r=1005; if(k==2){ if(odd_num!=0) l=dfs(i+1,odd_num-1,even_num,1); if(even_num!=0) r=dfs(i+1,odd_num,even_num,0); } else if(k==1){ if(odd_num!=0) l=dfs(i+1,odd_num-1,even_num,1); if(even_num!=0) r=dfs(i+1,odd_num,even_num-1,0)+1; } else if(k==0){ if(odd_num!=0) l=dfs(i+1,odd_num-1,even_num,1)+1; if(even_num!=0) r=dfs(i+1,odd_num,even_num-1,0); } dp[i][odd_num][even_num][k]=min(dp[i][odd_num][even_num][k]+l,dp[i][odd_num][even_num][k]+r); } return dp[i][odd_num][even_num][k]; } int main(){ n=read(); rp(i,1,n){ p[i]=read(); if(p[i]) visited[p[i]]=1; } rp(i,1,n){ if(!visited[i]){ if(i%2==1) s1.pb(i); else s2.pb(i); } } mst(dp,-1); printf("%d\n",dfs(1,s1.size(),s2.size(),2)); return 0; } /* 7 1 3 5 7 0 0 0 1 7 0 0 0 0 0 0 0 1 7 0 0 0 7 6 4 2 5 1 0 2 0 5 2 7 1 3 5 0 6 4 2 1 7 1 0 0 5 0 0 2 1 20 9 0 0 0 18 0 11 0 0 4 0 15 0 0 0 14 0 0 5 0 8 20 7 0 9 0 5 0 15 0 0 1 17 0 11 19 0 0 3 0 13 0 15 */
D题Numbers on Tree
题目大意:
首先定义一个节点的ci表示以这个树为根节点的子树中满足aj<ai的点的个数。
当然这个题不会让你求ci,不然就是一道sb题。
给你一颗树,以及每个节点的ci字,然后让你确定一下有没有满足条件的a数组,有的话输出YES并输出a数组,否则输出NO。a数组如果有多个,可以输出任意一个。
Input
5
0 1
1 3
2 1
3 0
2 0
OutputYES
2 3 2 1 2题解:
首先这个题的数据范围很小,所以我们可以考虑暴力维护一下子树的答案就行了,首先考虑怎么求出一个子树的答案。
如果这个子树的根节点的值为ci,表示子树中有ci个节点的a值小于它。
然后根据这个性质,我们可以暴力求出当前子树的a数组,然后把根节点插入到第ci+1位,后面的依次往后移就行了。
这样时间复杂度为O(n^2)的,其实这个题数据范围可以开大点,开到1e5都行,这样的话就需要用到dsu on tree,时间复杂度大致为O(nlogn)。
代码实现:
#pragma GCC optimize(2) #include<iostream> #include<algorithm> #include<cmath> #include<cstring> #include<cstdio> #include<cstdlib> #include<vector> #include<map> #include<set> #include<stack> #include<queue> #define PI atan(1.0)*4 #define E 2.718281828 #define rp(i,s,t) for (register int i = (s); i <= (t); i++) #define RP(i,t,s) for (register int i = (t); i >= (s); i--) #define ll long long #define ull unsigned long long #define mst(a,b) memset(a,b,sizeof(a)) #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 #define pii pair<int,int> #define mp make_pair #define pb push_back #define debug printf("ac\n"); using namespace std; inline int read() { int a=0,b=1; char c=getchar(); while(c<'0'||c>'9') { if(c=='-') b=-1; c=getchar(); } while(c>='0'&&c<='9') { a=(a<<3)+(a<<1)+c-'0'; c=getchar(); } return a*b; } const int INF = 0x3f3f3f3f; const int N = 2e3+7; vector<int> G[N]; int res[N],c[N]; int n; vector<int> dfs(int x){ vector<int> ans; for(auto v:G[x]){ vector<int> tmp=dfs(v); for(auto val:tmp) ans.pb(val); } if(x==0) return ans; if(ans.size()<c[x]){ cout<<"NO"<<endl; exit(0); } vector<int> temp; rp(i,0,c[x]-1) temp.pb(ans[i]); temp.pb(x); rp(i,c[x],(int)ans.size()-1) temp.pb(ans[i]); ans=temp; return ans; } int main(){ n=read(); rp(i,1,n){ int x=read(); c[i]=read(); G[x].pb(i); } vector<int> ans=dfs(0); cout<<"YES"<<endl; rp(i,0,ans.size()-1) res[ans[i]]=i+1; rp(i,1,n) cout<<res[i]<<" "; cout<<endl; return 0; }
Codeforces Round612(div2)——A-D题总结
最新推荐文章于 2022-04-02 16:22:00 发布