Pinely Round 2 (Div. 1 + Div. 2) (A~D)

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 ,使得a_{i} = MEX(a_{1} ,a_{2} ...,a_{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;
	}
}     

 

  • 4
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值