Hello 2023

A. Hall of Fame

统计一下向左照的最靠右和向右照的最靠左的看是否可以把所有的位置都覆盖

#include <bits/stdc++.h>
using namespace std;


int read(){
	int x = 0 , ch = getchar();
	while( ch < '0' || ch > '9' ) ch = getchar();
	while( ch >= '0' && ch <= '9' ) x = (x<<3)+(x<<1)+ch-'0' , ch = getchar();
	return x;
}

void solve(){
	int n = read();
	string s;
	cin >> s;
	int l = 0 , r = n+1;
	for( int i = 1 ; i <= n ; i ++ ){
		if( s[i-1] == 'L' ) l = i;
		else if( r == n+1 ) r = i;
	}
	// cout << l << " " << r << "\n";
	if( r < l ) cout << "0\n";
	else if( l+1 == r && r != n+1 && l != 0) cout << l << "\n";
	else cout << "-1\n";
	return;
}

int32_t main(){
	for( int t = read() ; t ; t -- )
		solve();
	return 0;
}

B. MKnez's ConstructiveForces Task

首先应该很容易就能发现如果\(n\)是偶数的情况\(1,-1,1,-1\cdots\)就行了吧。

那么就是来求一下\(n\)为奇数的情况了。首先\(n=2k+1\),然后根据题目得到

\[s_1+s_2+s_3+\cdots=s_1+s_2=s_2+s_3=s_3+s_4 \]

然后根据\(s_1+s_2=s_2+s_3\)可以推出\(s_1=s_3\),继续推导可以得到\(s_1=s_3=\cdots=s_{2k+1}\)

同理可以推出\(s_2=s_4=\cdots=s_{2k}\)

\(x=s_1=s_3=\cdots=s_{2k+1},y=s_2=s_4=\cdots=s_{2k}\)

\(s_1+s_2+s_3+\cdots=s_1+s_2\)可以推出\(s_3+s_4+\cdots+s_n=0\),代入上式可得

\(kx=(k-1)y\)\(x=(k-1),y=-k\)即可

注意当\(n=3\)时可以解出\(x=0\),但题目要求不等于零,所以此时无解

#include <bits/stdc++.h>
using namespace std;


int read(){
	int x = 0 , ch = getchar();
	while( ch < '0' || ch > '9' ) ch = getchar();
	while( ch >= '0' && ch <= '9' ) x = (x<<3)+(x<<1)+ch-'0' , ch = getchar();
	return x;
}

void solve(){
	int n; cin >> n;
	if( n % 2 == 0 ) {
		cout << "YES\n";
		for( int i = 1 ; i <= n ; i ++ )
			cout << ( i & 1 ? 1 : -1 ) << " \n"[i==n];
	}
	else if( n == 3 ) {
		cout << "NO\n";
	} else{
		cout << "YES\n";
		int x = 1 - ( n + 1 ) / 2 , y = n / 2 - 1;
		for( int i = 1 ; i <= n ; i ++ )
			cout << ( i & 1 ? y : x ) << " \n"[i==n];
	}
	return;
}

int32_t main(){
	ios::sync_with_stdio(false) , cin.tie(nullptr) , cout.tie(nullptr);
	int t; cin >> t;
	for( ; t ; t -- )
		solve();
	return 0;
}

C. Least Prefix Sum

题目的条件可以转换为,从\(m+1\)开始的前缀和大于0,从\(m_1\)开始的后缀和小于 0

然后再求的过程中用优先队列维护前缀后缀中的数字。

#include <bits/stdc++.h>
using namespace std;

#define int long long

int read(){
	int x = 0 , f = 1 , ch = getchar();
	while( ch != '-' && (ch < '0' || ch > '9') ) ch = getchar();
	if( ch == '-' ) f = -1 , ch = getchar();
	while( ch >= '0' && ch <= '9' ) x = (x<<3)+(x<<1)+ch-'0' , ch = getchar();
	return x*f;
}

void solve(){
	int n = read(), m = read(), res = 0;
	vector<int> a(n+1);
	for( int i = 1 ; i <= n ; i ++ ) a[i] = read();
	priority_queue<int> q;
	for( int i = m , sum = 0 , u ; i > 1 ; i -- ){
		sum += a[i] , q.push(a[i]);
		while( sum > 0 )
			u = q.top(), q.pop() , sum -= u * 2 , q.push(-u), res ++;
	}
	priority_queue<int,vector<int>,greater<int>> p;
	for( int i = m+1 , sum = 0 , u ; i <= n ; i ++ ){
		sum += a[i] , p.push(a[i]);
		while( sum < 0 )
			u = p.top(), p.pop() , sum -= u * 2 , p.push(-u) , res ++;
	}
	printf("%lld\n" , res);
	return;
}

int32_t main(){
	for( int t = read() ; t ; t -- )
		solve();
	return 0;
}

D. Boris and His Amazing Haircut

如果\(a_i<b_i\)则一定不可以。反之\(a_i>=b_i\)可以进行若干次操作。但要保证\(a_i=b_i\)或至少有一次操作\(x=b_i\)

我们把\(x=b_i\)称为关键操作,然后关键操作是可以合并的,我们要尽可能的合并关键操作,而合并关键操作的条件是\(x_i=x_j\),且\(\max(x_{i+1}\cdots x_{j-1})>=x_i\),所以我们要解决的问题就是区间查询最值,我选择使用 ST表解决

#include <bits/stdc++.h>
using namespace std;

int read(){
	int x = 0 , ch = getchar();
	while( ch < '0' || ch > '9' ) ch = getchar();
	while( ch >= '0' && ch <= '9' ) x = (x<<3)+(x<<1)+ch-'0' , ch = getchar();
	return x;
}

const int N = 2e5+5;

int f[N][20] , log_2[N] , a[N] , b[N];

void solve(){
	int n = read();
	for( int i = 1 ; i <= n ; i ++ ) a[i] = read();
	for( int i = 1 ; i <= n ; i ++ ) b[i] = read();
	map<int,int> c;
	for( int m = read() , x ; m ; m -- ) x = read() , c[x] ++;
	map<int,vector<int>> cnt;
	for( int i = 1 ; i <= n ; i ++ ){
		if( a[i] < b[i] ) return printf("NO\n") , void();
		else if( a[i] == b[i] ) continue;
		cnt[ b[i] ].push_back(i);
	}
	for( int i = 1 ; i <= n ; i ++ ) f[i][0] = b[i];
	for( int j = 1 ; j <= log_2[n] ; j ++ )
		for( int i = 1; i + ( 1<<j) - 1 <= n ; i ++ )
			f[i][j] = max( f[i][j-1] , f[i+(1<<j-1)][j-1] );
	for( const auto &[k , v] : cnt ){
		for( int i = 1 , l , r , s , t; i < v.size() ; i ++ ){
			l = v[i-1] , r = v[i] , s = log_2[r - l + 1] , t = max( f[l][s] , f[r-(1<<s)+1][s] );
			if( t <= k ) c[k] ++; 
		}
		if( v.size() <= c[k] ) continue;
		printf("NO\n");
		return;
	}
	printf("YES\n");
	return;
}

int32_t main(){
	log_2[0] = -1;
	for( int i = 1 ; i < N ; i ++ ) log_2[i] = log_2[i>>1] + 1;

	for( int t = read() ; t ; t -- ) solve();
	return 0;
}
posted @ 2023-03-15 21:55  PHarr  阅读(31)  评论(0编辑  收藏  举报