E题读不懂啊...
1863A - Channel
题意:你发布了一条消息,其中你有n个订阅者,其中m个订阅者已经处于在线状态,现有k个消息,其中如果消息为‘+’,则代表订阅者中有一个人上线了,若消息为‘-’,则代表订阅者中有一个人下线了。假设上线的人都能看到你的消息,求在给定的k条消息中能否得出结论:所有订阅者都看到过你的消息。输出yes 、 maybe 、no。
思路:如果要是yes,考虑极端情况:每次上线的人都尽可能的是之前已经上线然后又下线的。那么必须满足所有订阅者都同时在线。 如果是no,同样考虑极端情况:每次上线的人都是之前未上线的人。那么必须满足‘+’ 的消息数量 + m < n ,这样才是no。其余情况都是maybe。
void solve()
{
int n , m , k , t;
cin>>n>>m>>k;
int cnt = 0;
t = m;
int m_max = m;
for(int i = 0 ; i < k ; i ++){
char c;
cin>>c;
if(c == '+'){
m ++;
cnt++;
m_max = max(m_max , m);
}
else{
m--;
}
}
if(m_max == n){
cout<<"YES\n";
}
else{
if(t + cnt >= n){
cout<<"MAYBE\n";
}
else{
cout<<"NO\n";
}
}
}
1863B - Split Sort
题意:给定序列a,你可以进行操作:选择一个数 x ,将所有 比 x 小的数按照序列中的顺序放到 x 前面 , 将所有大于等于 x 的数 按照序列中的顺序放到 x 后面。求整个序列满足单增的最小操作数。
思路:直接观察给的例子:
6
6 4 3 5 2 1
第一步选择了 4 , 它能够将所有小于4的数放到4前面,4原本是在3前面的,肯定不满足递增条件,而本次操作将4放到了3的后面,能够满足递增条件。第二步选择6,满足了6放到5的后面。第三步选择3,满足了3放到2的后面。最后一步选择2,满足2放到1的后面。自此操作完成。因此得到结论:操作数为整个序列中 i 和 i + 1 位置的逆序对数量。
typedef pair<int,int>pl;
int cmp1(pl a , pl b){
return a.x < b.x;
}
void solve()
{
int n;
cin>>n;
pl a[n];
for(int i = 0 ; i < n ; i ++){
int x;
cin>>x;
a[i].first = x;
a[i].second = i;
}
sort(a , a + n , cmp1);
int cnt = 0;
for(int i = 1 ; i < n ; i ++){
if(a[i].y < a[i - 1].y){
cnt++;
}
}
cout<<cnt<<endl;
}
1863C - MEX Repetition
题意:给定一个长度为n,大小为[0,n]的两两互不相同的序列。总共进行k轮操作,每轮操作将按照顺序从 i = 1 ~ n ,使得。其中MEX函数代表了所有数当中没有出现的最小非负整数。例如MEX(1,1,2) = 0 , MEX(0,1,2)= 3。
思路:[0,n]共有n + 1个数,而序列总共有n个,因此假设未出现的数为x,则第一轮过程当中整个序列将变为[ x , a0 , a1 , a2 , a3 ... an-1]。 此时an 是没有出现的,那么第二轮就变成了[an , x , a0 , x1 , x2 , .... an-2] 。如此往复,找到规律即可。
void solve()
{
int n , k;
cin>>n>>k;
vector<int>ans;
map<int,int>mp;
for(int i = 0 ; i < n ; i ++){
int x;
cin>>x;
ans.pb(x);
mp[x] = 1;
}
for(int i = 0 ; i <= n ; i++){
if(mp[i] == 0){
ans.pb(i);
}
}
int t = n + 1;
int s = k % t;
int st = t - s;
for(int i = 0 ; i < n ; i ++){
cout<<ans[st % t]<<" ";
st++;
}
cout<<endl;
}
1863D - Two-Colored Dominoes
题意:有一个n * m 的网格。其中有若干个1 * 2的多米诺骨牌横着放或者竖着放在其中,你需要将其一格涂成黑色,一格涂成白色。需要满足一行当中白色的格子等于黑色的格子,一列当中白色的格子等于黑色的格子。
思路:对于每一个横着放的多米诺骨牌,它不会对当前行造成影响。他只会对所在列造成影响。于是我们可以将处在同两列的横着放的多米诺骨牌两两配对,分别是左白右黑和左黑右白。这样就不会对两列造成影响了。竖着放的也是同理,若能够两两配对,则能够满足题意,若不能两两配对,那么就不能满足。
void solve()
{
int n , m;
cin>>n>>m;
char a[n][m];
vector<int>row[m] , column[n];
for(int i = 0 ; i < n ; i ++){
for(int j = 0 ; j < m ; j ++){
cin>>a[i][j];
if(a[i][j] == 'L'){
row[j].pb(i);
}
if(a[i][j] == 'U'){
column[i].pb(j);
}
}
}
for(int i = 0; i < m ; i++){
if(row[i].size() % 2 == 1){
cout<<"-1\n";
return;
}
else{
int t = row[i].size();
int flag = 1;
for(int j = 0 ; j < t ; j ++){
int r = row[i][j];
if(flag == 1){
a[r][i] = 'W';
a[r][i + 1] = 'B';
flag *= -1;
}
else{
a[r][i] = 'B';
a[r][i + 1] = 'W';
flag *= -1;
}
}
}
}
for(int i = 0 ; i < n ; i ++){
if(column[i].size() % 2 == 1){
cout<<"-1\n";
return;
}
else{
int t = column[i].size();
int flag = 1;
for(int j = 0 ; j < t ; j ++){
int c = column[i][j];
if(flag == 1){
a[i][c] = 'W';
a[i + 1][c] = 'B';
flag*=-1;
}
else{
a[i][c] = 'B';
a[i + 1][c] = 'W';
flag*= -1;
}
}
}
}
for(int i = 0 ; i < n ; i++){
for(int j = 0; j < m ; j ++){
cout<<a[i][j];
}
cout<<endl;
}
}