CF1792

CF1792

GamingForces

如果是 \(1\) 那么尝试一次消除两个 如果 \(\ge 2\) 那么血量 \(-1\) 的操作一定不优 直接删掉即可

#include <bits/stdc++.h>
using namespace std;
#define endl '\n'
#define inl inline
#define eb emplace_back
#define mid (l+r>>1)
#define getchar() cin.get()
#define print(x) cout<<#x<<'='<<x<<endl
const int N = 1e5 + 5;
const int maxn = 1e5;
const int inf = 0x3f3f3f3f;

int read()
{
	int f = 1 , x = 0;
	char ch = getchar();
	while ( !isdigit(ch) ) { if ( ch == '-' ) f = -1; ch = getchar(); }
	while ( isdigit(ch) ) { x = ( x << 1 ) + ( x << 3 ) + ( ch ^ 48 ); ch = getchar(); }
	return x * f;
}

int n , a[N] , cnt; 

signed main ()
{
	ios::sync_with_stdio(false);
	cin.tie(0) , cout.tie(0);
	
	int T = read();
	while ( T -- )
	{
		cnt = 0;
		n = read();
		for ( int i = 1 ; i <= n ; i ++ ) a[i] = read() , cnt += ( a[i] == 1 );
		cout << n - cnt + ( cnt / 2 + cnt % 2 ) << endl;
	}
	return 0;
}

Stand-up Comedian

首先 如果没有 \(a_1\) 那么说任何一个相声都会让人离场

否则 我们优先将 \(a_1\) 说完 那么此时 \(a_2\) 操作和 \(a_3\) 操作可以相互抵消 也就是我们可以说 \(min(a_2,a_3)\times 2\) 场相声

此时两个人的满意度依旧是 \(a_1\) 那么此时只剩 \(a_2/a_3\) 中的一个操作和 \(a_4\) 操作了 那么我们直接将剩下的场在合法条件下都说完 计入答案为 \(\min (a_1+1,abs(a_3-a_2)+a_4)\)

#include <bits/stdc++.h>
using namespace std;
#define endl '\n'
#define inl inline
#define eb emplace_back
#define mid (l+r>>1)
#define getchar() cin.get()
#define print(x) cout<<#x<<'='<<x<<endl
const int N = 1e5 + 5;
const int maxn = 1e5;
const int inf = 0x3f3f3f3f;

int read()
{
	int f = 1 , x = 0;
	char ch = getchar();
	while ( !isdigit(ch) ) { if ( ch == '-' ) f = -1; ch = getchar(); }
	while ( isdigit(ch) ) { x = ( x << 1 ) + ( x << 3 ) + ( ch ^ 48 ); ch = getchar(); }
	return x * f;
}

int n , a[N] , cnt; 

signed main ()
{
	ios::sync_with_stdio(false);
	cin.tie(0) , cout.tie(0);
	int T = read();
	while ( T -- )
	{
		int a1 = read() , a2 = read() , a3 = read() , a4 = read();
		if ( a1 == 0 ) { cout << 1 << endl; continue; }
		cout << a1 + 2 * min ( a2 , a3 ) + min ( a1 + 1 , abs ( a3 - a2 ) + a4 ) << endl;
	}
	return 0;
}

Min Max Sort

我们对于这类排列的题目 可以记录 \(p[x]=i\) 数组表示 \(x\) 这个数在原来序列中的位置

假设 \(k\) 次操作可以归位 那么 \(1\sim k\)\(n-k+1\sim n\) 都被移动过了 而其余的相对位置并没有移动(也就是 \(pos[i]\) 的相对大小关系没有移动)

那么我们令 \(k=\frac n 2\) 那么从中间开始判断中间的 \(p[i]\) 是否符合递增即可 如果不符合递增 那么直接 \(break\) 并输出 \(k\)

#include <bits/stdc++.h>
using namespace std;
#define endl '\n'
#define inl inline
#define eb emplace_back
#define mid (l+r>>1)
#define getchar() cin.get()
#define print(x) cout<<#x<<'='<<x<<endl
const int N = 2e5 + 5;
const int inf = 0x3f3f3f3f;

int read()
{
	int f = 1 , x = 0;
	char ch = getchar();
	while ( !isdigit(ch) ) { if ( ch == '-' ) f = -1; ch = getchar(); }
	while ( isdigit(ch) ) { x = ( x << 1 ) + ( x << 3 ) + ( ch ^ 48 ); ch = getchar(); }
	return x * f;
}

int n , p[N] ; 

signed main ()
{
	ios::sync_with_stdio(false);
	cin.tie(0) , cout.tie(0);
	int T = read();
	while ( T -- )
	{
		n = read();
		for ( int i = 1 ; i <= n ; i ++ ) p[read()] = i;
		int k = n / 2;
		while ( k && p[k] < p[k+1] && p[n-k] < p[n-k+1] ) -- k;
		cout << k << endl;
	}
	return 0;
}

Fixed Prefix Permutations

\(D\) 了 怎么会是呢()

如果 \(p*q\) 的美丽度为 \(k\) 那么当 \(i\le k\)\(q_{p_i}=i\)

我们令 \(q'\)\(q\) 的逆排列 即 \(q'_{q_i}=i\)

此时如果 \(p * q\) 的美丽度为 \(k\) 那么 \(q'_{q_{p_i}} =q'_i=p_i\) 那么我们要求 \(q'\)\(p\) 的最长公共前缀

\(trie\) 维护所有 \(q'\) 枚举每一个排列 在字典树上匹配即可 时间复杂度 \(O(nm)\)

字典树的清零好玄学...

#include <bits/stdc++.h>
using namespace std;
#define endl '\n'
#define inl inline
#define eb emplace_back
#define mid (l+r>>1)
#define getchar() cin.get()
#define print(x) cout<<#x<<'='<<x<<endl
const int N = 5e5 + 5;
const int inf = 0x3f3f3f3f;

int read()
{
	int f = 1 , x = 0;
	char ch = getchar();
	while ( !isdigit(ch) ) { if ( ch == '-' ) f = -1; ch = getchar(); }
	while ( isdigit(ch) ) { x = ( x << 1 ) + ( x << 3 ) + ( ch ^ 48 ); ch = getchar(); }
	return x * f;
}

int n , m , temp[N] , mp[N][15] , t[N][15] , tot , ans; 

struct Tree
{
	int cnt , t[N][15];
	void clear()
	{
		for ( int i = 0 ; i <= cnt ; i ++ ) memset ( t[i] , 0 , sizeof t[i] );
		cnt = 0;
	}
	void insert ( int a[] )
	{
		int p = 0;
		for ( int i = 1 ; i <= m ; i ++ )
		{
			if ( !t[p][a[i]] ) t[p][a[i]] = ++cnt;
			p = t[p][a[i]];
		}
	}
	int query ( int a[] )
	{
		int p = 0 , tot = 0;
		for ( int i = 1 ; i <= m ; i ++ )
		{
			if ( t[p][a[i]] ) ++ tot , p = t[p][a[i]];
			else return tot;
		}
		return tot;
	}
}T;

signed main ()
{
	ios::sync_with_stdio(false);
	cin.tie(0) , cout.tie(0);
	int TT = read();
	while ( TT -- )
	{
		T.clear();
		n = read() , m = read();
		for ( int i = 1 ; i <= n ; i ++ ) 
		{
			for ( int j = 1 ; j <= m ; j ++ ) mp[i][j] = read();
			for ( int j = 1 ; j <= m ; j ++ ) temp[mp[i][j]] = j;
			T.insert(temp);
		}
		for ( int i = 1 ; i <= n ; i ++ ) cout << T.query ( mp[i] ) << ' ';
		cout << endl;
	}
	return 0;
}
 

Divisors and Table

我们可以先通过分解 \(m_1\)\(m_2\) 并交叉相乘来求出 \(m\) 的所有因数

对于 \(m\) 的一个因数 \(c_i\) 它所在的行号一定是 \(c_i\) 的因数 所以我们可以二分找到最小的 \(k\) 使得 \(\lceil \frac {c_i} {c_k} \rceil \le n\) (相当于列号 \(\le n\) )

因为 \(c_i\) 的因数一定是 \(m\) 的因数 所以我们从 \(c_k\) 开始往后跳 直到 \(c_j|c_i\) 或者 \(c_j>n\) 为止

#include <bits/stdc++.h>
using namespace std;
#define endl '\n'
#define inl inline
#define eb emplace_back
#define mid (l+r>>1)
#define getchar() cin.get()
#define print(x) cout<<#x<<'='<<x<<endl
#define int long long
const int N = 5e5 + 5;
const int inf = 0x3f3f3f3f;

int read()
{
	int f = 1 , x = 0;
	char ch = getchar();
	while ( !isdigit(ch) ) { if ( ch == '-' ) f = -1; ch = getchar(); }
	while ( isdigit(ch) ) { x = ( x << 1 ) + ( x << 3 ) + ( ch ^ 48 ); ch = getchar(); }
	return x * f;
}

int n , m1 , m2 , cnt , ans;
vector<int> a , b , c;

signed main ()
{
	ios::sync_with_stdio(false);
	cin.tie(0) , cout.tie(0);
	int TT = read();
	while ( TT -- )
	{
		a.clear() , b.clear() , c.clear() , cnt = ans = 0;
		n = read() , m1 = read() , m2 = read();
		for ( int i = 1 ; i <= m1 / i ; i ++ )
			if ( m1 % i == 0 )
			{
				a.eb(i);
				if ( m1 / i != i ) a.eb(m1/i);
			}
		for ( int i = 1 ; i <= m2 / i ; i ++ )
			if ( m2 % i == 0 )
			{
				b.eb(i);
				if ( m2 / i != i ) b.eb(m2/i);
			}
		for ( auto v1 : a ) for ( auto v2 : b ) c.eb(v1*v2);
		sort ( c.begin() , c.end() );
		c.erase ( unique ( c.begin() , c.end() ) , c.end() );
		for ( int i = 0 ; i < c.size() ; i ++ )
		{
			int l = lower_bound ( c.begin() , c.end() , ( c[i] - 1 ) / n + 1 ) - c.begin();
			for ( int j = l ; j < c.size() ; j ++ )
			{
				if ( c[j] > n ) break;
				if ( c[i] % c[j] == 0 ) { ++ cnt , ans ^= c[j]; break; }
			}
		}
		cout << cnt << ' ' << ans << endl;
	}
	return 0;
}
posted @ 2023-10-31 17:40  Echo_Long  阅读(325)  评论(0编辑  收藏  举报