Codeforces Round #612 (Div. 2)
题库链接
https://codeforces.com/contest/1287
A. Angry Students
n个人,生气的人A会丢雪球打不生气的人,然后不生气的生气了
模拟
#include <bits/stdc++.h>
using namespace std;
#define mem(a,b) memset(a,b,sizeof(a))
#define cin(a) scanf("%d",&a)
#define pii pair<int,int>
#define ll long long
#define gcd __gcd
const int inf = 0x3f3f3f3f;
const int maxn = 200100;
const int M = 1e9+7;
int n,m,k,t;
char s[110];
bool solve()
{
bool flag = 0;
for(int i = 0; i < n-1; i++)
{
if(s[i] == 'A' && s[i+1] == 'P')
{
flag = 1;
s[i+1] = 'A';
i++;
}
}
//cout<<s<<endl;
return flag;
}
int main()
{
#ifdef ONLINE_JUDGE
#else
freopen("data.in", "r", stdin);
#endif
cin(t);
while(t--)
{
cin(n);
cin>>s;
int ans = 0;
while(solve()) ans++;
cout<<ans<<endl;
}
return 0;
}
B. Hyperset
有一副牌,k个属性,选出三张,对于每个属性,要么全部相同,要么全部不同
暴力匹配,只需要枚举前两张牌,用hash记录一下
#include <bits/stdc++.h>
using namespace std;
#define mem(a,b) memset(a,b,sizeof(a))
#define cin(a) scanf("%d",&a)
#define pii pair<int,int>
#define ll long long
#define gcd __gcd
const int inf = 0x3f3f3f3f;
const int maxn = 2000;
const int M = 1e9+7;
int n,m,k,t;
char s[maxn][32];
map<string,int> mp;
bool vis[3];
bool judge(int i,int j)
{
char str[32];
for(int l = 0; l < m; l++)
{
vis[1] = vis[2] = vis[0] = 0;
if(s[i][l] == s[j][l]) str[l] = s[i][l];
else
{
if(s[i][l] == 'S' || s[j][l] == 'S') vis[0] = 1;
if(s[i][l] == 'E' || s[j][l] == 'E') vis[1] = 1;
if(s[i][l] == 'T' || s[j][l] == 'T') vis[2] = 1;
if(!vis[0]) str[l] = 'S';
else if(!vis[1]) str[l] = 'E';
else if(!vis[2]) str[l] = 'T';
}
}
str[m] = '\0';
//cout<<s[i]<<' '<<s[j]<<' '<<str<<' '<<mp[str]<<endl;
if(mp[str] > j) return true;
return false;
}
int main()
{
#ifdef ONLINE_JUDGE
#else
freopen("data.in", "r", stdin);
#endif
cin(n);cin(m);
for(int i = 0; i < n; i++)
{
scanf("%s",s[i]);
mp[s[i]] = i;
}
int ans = 0;
for(int i = 0; i < n; i++)
{
for(int j = i+1; j < n; j++)
{
if(judge(i,j)) ans++;
}
}
cout<<ans<<endl;
return 0;
}
C. Garland
有一个序列,1-n,0代表空,如何填充这个序列,使得相邻灯泡奇偶对数最小
dp,dp[i][j][k]表示前i个数,用了j个偶数,k表示第i个数是奇数还是偶数
#include <bits/stdc++.h>
using namespace std;
#define mem(a,b) memset(a,b,sizeof(a))
#define cin(a) scanf("%d",&a)
#define pii pair<int,int>
#define ll long long
#define gcd __gcd
const int inf = 0x3f3f3f3f;
const int maxn = 110;
const int M = 1e9+7;
int n,m,k,t;
int a[maxn];
int dp[maxn][maxn][2];
int main()
{
#ifdef ONLINE_JUDGE
#else
freopen("data.in", "r", stdin);
#endif
cin(n);
for(int i = 1; i <= n; i++)
{
cin(a[i]);
}
mem(dp,inf);
dp[0][0][0] = dp[0][0][1] = 0;
for(int i = 1; i <= n; i++)
{
for(int j = 0; j <= i; j++)
{
if(a[i]%2 == 0)
{
dp[i][j][0] = min(dp[i-1][j-1][0],dp[i-1][j-1][1]+1);
}
if(a[i]%2 || a[i]==0)
{
dp[i][j][1] = min(dp[i-1][j][1],dp[i-1][j][0]+1);
}
}
}
cout<<min(dp[n][n/2][0],dp[n][n/2][1])<<endl;
return 0;
}
D. Numbers on Tree
n个节点,每一个节点有一个值,并且有一个c,表示他的子孙里面有c个值比他的值小
题目给出树的结构和c的值,求出满足题意的节点的值
#include <bits/stdc++.h>
using namespace std;
#define mem(a,b) memset(a,b,sizeof(a))
#define cin(a) scanf("%d",&a)
#define pii pair<int,int>
#define ll long long
#define gcd __gcd
const int inf = 0x3f3f3f3f;
const int maxn = 2100;
const int M = 1e9+7;
int n,m,k,t;
int c[maxn];
int sz[maxn]; //记录i有多少个节点
int ans[maxn];
vector<int> a[maxn]; //图
vector<int> rk;
void dfs(int u,int fa)
{
sz[u] = 1;
for(auto v : a[u])
{
if(v!=fa) dfs(v,u);
sz[u] += sz[v];
}
if(c[u] >= sz[u])
{
puts("NO");exit(0);
}
rk.insert(rk.begin()+c[u],u);
}
int main()
{
#ifdef ONLINE_JUDGE
#else
freopen("data.in", "r", stdin);
#endif
cin(n);
int root = 0;
for(int i = 1,x; i <= n; i++)
{
scanf("%d%d",&x,&c[i]);
if(x == 0) root = i;
else a[x].push_back(i);
}
dfs(root,0);
for(int i = 0; i < n; i++)
{
ans[rk[i]] = i+1;
}
puts("YES");
for(int i = 1; i <= n; i++)
{
cout<<ans[i]<<' ';
}
return 0;
}
E1. Madhouse (Easy version)
给定一个字符串长度n,你有三次询问机会,? l r
表示询问区间[l,r],返回区间[l,r]的全部子串,但是顺序会打乱,求出这个字符串
其实我们只需要询问两次就好了,询问? 1 n
和? 2 n
,并且用第一次的结果减去第二次的结果,你就会发现你只剩下n个不同长度的字符串了
#include <bits/stdc++.h>
using namespace std;
#define mem(a,b) memset(a,b,sizeof(a))
#define cin(a) scanf("%d",&a)
#define pii pair<int,int>
#define ll long long
#define gcd __gcd
const int inf = 0x3f3f3f3f;
const int maxn = 110;
const int M = 1e9+7;
int n,m,k,t;
multiset <string> st;
string ans = " ";
string f[maxn];
int main()
{
#ifdef ONLINE_JUDGE
#else
freopen("data.in", "r", stdin);
#endif
cin(n);
cout<<"? 1 "<<n<<endl;
fflush(stdout);
for(int i = 1; i <= n; i++)
{
for(int j = i; j <= n; j++) //长度为i的有n-i+1个
{
string tmp;
cin>>tmp;
sort(tmp.begin(),tmp.end());
st.insert(tmp); //插入
}
}
if(n == 1)
{
cout<<"! "<<*st.begin()<<endl;
return 0;
}
cout<<"? 2 "<<n<<endl;
fflush(stdout);
for(int i = 2; i <= n; i++)
{
for(int j = i; j <= n; j++)
{
string tmp;
cin>>tmp;
sort(tmp.begin(),tmp.end());
st.erase(st.find(tmp)); //只删除一个,如果是st.erase(tmp);会删除多个
}
}
//st里面只剩下n个数,而且是n个长度不同的数
for(auto tmp : st)
{
f[tmp.size()] = tmp;
}
ans += f[1];
int mark[30];
for(int j = 2; j <= n; j++)
{
mem(mark,0);
for(auto i : f[j])
{
mark[i-'a']++;
}
for(auto i : ans)
{
mark[i-'a']--;
}
for(int i = 0; i < 30; i++)
{
if(mark[i]) ans += char(i+'a');
}
}
cout<<"!"<<ans<<endl;
return 0;
}