Codeforces Round #612 Div. 2
链接https://codeforces.com/contest/1287
A. Angry Students(简单模拟)
题意:从A开始从左往右扔雪球,问最后一个变生气的人,经过了多少秒
思路:
- 记录位置
- 遇到A重新开始计数,取最大值
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=1e5+5,maxm=1e5+5;
const int mod=1e9+7,inf=0x7f7f7f7f;
int t,n;
string s;
int main()
{
cin>>t;
while(t--)
{
cin>>n>>s;
vector<int> pos;
for(int i=0;i<n;++i)
if(s[i]=='A')
pos.push_back(i);
if(pos.size()==0)
puts("0");
else
{
pos.push_back(n);
int ans=0;
for(int i=1;i<pos.size();++i)
ans=max(ans,pos[i]-pos[i-1]-1);
cout<<ans<<"\n";
}
}
return 0;
}
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int mod=1e9+7;
const int maxn=1e5+10;
int t,n;
string s;
int main()
{
cin>>t;
while(t--)
{
cin>>n>>s;
bool valid=false;
int ans=0,cnt=0;
for(int i=0;i<s.size();++i)
{
if(s[i]=='A')
cnt=0,valid=true;
else
cnt++;
if(valid&&ans<cnt)
ans=cnt;
}
printf("%d\n",ans);
}
return 0;
}
B. Hyperset(枚举+读题)
题意:找三元组,每一个元素都有k个属性,对于第
i
i
i个属性要求两两不同或者全部相同
思路:枚举第一个元素和第二个元素,同时构造出需要的第三个元素。在map里面查找这个元素,存在的话 ans++
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=1500+5,maxm=1e5+5;
const int mod=1e9+7,inf=0x7f7f7f7f;
int n,k;
map<string,int> m;
string s[maxn];
int main()
{
cin>>n>>k;
for(int i=1;i<=n;++i)
{
cin>>s[i];
m[s[i]]=i;
}
int cnt=0;
for(int i=1;i<=n-2;++i)
{
for(int j=i+1;j<=n-1;++j)
{
string ans;
for(int p=0;p<k;++p)
{
if(s[i][p]==s[j][p])
ans+=s[i][p];
else if(s[i][p]!='S'&&s[j][p]!='S')
ans+='S';
else if(s[i][p]!='E'&&s[j][p]!='E')
ans+='E';
else if(s[i][p]!='T'&&s[j][p]!='T')
ans+='T';
}
if(m[ans]>j)
cnt++;
}
}
cout<<cnt<<"\n";
return 0;
}
C. Garland(DP)
题意:n 个位置填数,填完之后为 n 的排列。0 代表位置为空,要求使得填完之后,前后的奇偶性差别最小。即
a
b
s
(
p
i
+
1
−
p
i
)
%
2
=
=
1
abs(p_{i+1}-p_{i}) \% 2==1
abs(pi+1−pi)%2==1 的数量最少
思路:
d
p
[
i
]
[
j
]
[
k
]
[
0
/
1
]
dp[i][j][k][0/1]
dp[i][j][k][0/1]表示前 i 个数还剩 j 个偶数 k 个奇数,0 代表当前位填偶数,1 代表当前位填奇数
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=1e5+5,maxm=1e5+5;
const int mod=1e9+7,inf=0x7f7f7f7f;
int n;
int a[maxn],pref[maxn];
int dp[110][110][110][2];
int main()
{
cin>>n;
int odd=(n+1)/2;
int even=n-odd;
for(int i=1;i<=n;++i)
{
scanf("%d",&a[i]);
if(a[i]>0)
{
if(a[i]&1)
odd--;
else
even--;
}
pref[i]=pref[i-1]+(a[i]==0?1:0);
}
memset(dp,0x3f,sizeof(dp));
dp[0][0][0][0]=0;
dp[0][0][0][1]=0;
for(int i=1;i<=n;++i)
{
for(int j=0;j<=even;++j)
{
for(int k=0;k<=odd;++k)
{
if(j+k>pref[i])
continue;
if(a[i]>0)
{
if(a[i]&1)
dp[i][j][k][1]=min(dp[i-1][j][k][0]+1,dp[i-1][j][k][1]);
else
dp[i][j][k][0]=min(dp[i-1][j][k][0],dp[i-1][j][k][1]+1);
}
else
{
dp[i][j][k][0]=min(dp[i-1][j-1][k][0],dp[i-1][j-1][k][1]+1);
dp[i][j][k][1]=min(dp[i-1][j][k-1][0]+1,dp[i-1][j][k-1][1]);
}
}
}
}
int ans=min(dp[n][even][odd][0],dp[n][even][odd][1]);
cout<<ans<<"\n";
return 0;
}
D. Numbers on Tree(DFS构造+思维)
题意:给定一棵树,给定数组
c
c
c ,
c
i
c_i
ci表示子树中点权值小于自己的数量。请你构造出当前树的点权值
a
a
a
思路:在子树构造完成之后,在合适的位置插入自己的位置
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=2000+5,maxm=1e5+5;
const int mod=1e9+7,inf=0x7f7f7f7f;
int n;
int p[maxn],c[maxn],a[maxn];
vector<int> G[maxn];
vector<int> dfs(int u,int fa)
{
vector<int> t;
for(auto v : G[u])
{
if(v==fa)
continue;
vector<int> b=dfs(v,u);
for(auto i : b)
t.push_back(i);
}
if(c[u]>t.size())
{
puts("NO");
exit(0);
}
t.insert(t.begin()+c[u],u);
return t;
}
int main()
{
cin>>n;
int root=-1;
for(int i=1;i<=n;++i)
{
int v,x;
scanf("%d%d",&v,&x);
if(v==0)
root=i;
else
{
G[i].push_back(v);
G[v].push_back(i);
}
c[i]=x;
}
vector<int> p=dfs(root,-1);
for(int i=1;i<=n;++i)
a[p[i-1]]=i;
puts("YES");
for(int i=1;i<=n;++i)
cout<<a[i]<<" ";
puts("");
return 0;
}