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;
}