CF1798
CF1798
随的div2构造场 真是想不出来
Showstopper
乱搞过了
我们钦定 \(b[n]\) 比 \(a[n]\) 小 那么我们如果 \(b[i]>b[n]\) 的话 那么别无他法 只能换一下 如果换了也不行 直接判无解即可
#include <bits/stdc++.h>
using namespace std;
#define endl '\n'
#define inl inline
#define eb emplace_back
#define pii pair<int,int>
#define fi first
#define se second
#define getchar() cin.get()
const int N = 100 + 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 , a[N] , b[N] , tmp[2] , maxx;
signed main ()
{
ios::sync_with_stdio(false);
ios::sync_with_stdio(false);
cin.tie(0) , cout.tie(0);
int T = read();
while ( T -- )
{
n = read();
generate ( a + 1 , a + n + 1 , read );
generate ( b + 1 , b + n + 1 , read );
if ( a[n] < b[n] ) swap ( a[n] , b[n] );
for ( int i = 1 ; i <= n - 1 ; i ++ )
{
tmp[0] = a[i] , tmp[1] = b[i];
if ( min ( tmp[0] , tmp[1] ) > b[n] ) { cout << "No" << endl; goto flg; }
else if ( tmp[1] > b[n] ) swap ( a[i] , b[i] );
}
maxx = -inf;
for ( int i = 1 ; i <= n ; i ++ ) maxx = max ( maxx , a[i] );
if ( maxx != a[n] ) { cout << "No" << endl; goto flg; }
cout << "Yes" << endl;
flg:;
}
return 0;
}
Three Sevens
简单构造题 发现对于每一个人 只有最后一次买彩票中奖才有用
那么我们直接开 \(lst[i]\) 数组表示 \(i\) 人最后一次买彩票的场次 我们再开一个数组 \(cnt[i]\) 表示 \(i\) 天对应的中奖人编号
那么我们扫一遍值域为 \(cnt\) 数组赋值 最后扫一遍 \(cnt\) 数组判断无解或者输出方案即可
#include <bits/stdc++.h>
using namespace std;
#define endl '\n'
#define inl inline
#define eb emplace_back
#define pii pair<int,int>
#define fi first
#define se second
#define getchar() cin.get()
const int N = 5e4 + 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[N] , m , lst[N] , vis[N];
signed main ()
{
ios::sync_with_stdio(false);
cin.tie(0) , cout.tie(0);
int T = read();
while ( T -- )
{
memset ( vis , 0 , sizeof vis );
memset ( lst , 0 , sizeof lst );
m = read();
for ( int i = 1 ; i <= m ; i ++ )
{
n[i] = read();
for ( int j = 1 ; j <= n[i] ; j ++ ) lst[read()] = i;
}
for ( int i = 1 ; i <= 50000 ; i ++ ) if ( lst[i] ) vis[lst[i]] = i;
int flag = 1;
for ( int i = 1 ; i <= m ; i ++ ) if ( !vis[i] ) { flag = 0; break; }
if ( !flag ) cout << -1 << endl;
else
{
for ( int i = 1 ; i <= m ; i ++ ) cout << vis[i] << ' ';
cout << endl;
}
}
return 0;
}
Candy Store
想不到www
假设一个标签 \(tag\) 概括了 \(l\) 到 \(r\) 种糖果的标签 则我们设 \(tag=c_{l\sim r}\)
\(\because c_i=d_i\times b_i\),
\(\therefore b_{l\sim r}\mid tag\)
\(\therefore \operatorname{lcm}(b_l,b_{l+1}\dots b_r)\mid tag\)
\(\because d_i\mid a_i\)
\(\therefore c_i\mid a_i\times b_i\)
\(\therefore tag\mid \gcd(a_l\times b_l,a_{l+1}\times b_{l+1}\dots a_r\times b_r)\)
\(\therefore \operatorname{lcm}(b_l,b_{l+1}\dots b_r)\mid \gcd(a_i\times b_i,a_{i+1}\times b_{i+1}\dots a_r\times b_r)\)
所以只要判断当前 \(\gcd\) 是否能被 \(\operatorname{lcm}\) 整除即可 如果不能 将 \(\gcd\) 更新成 \(a_i\times b_i\) \(\operatorname{lcm}\) 更新成 \(b_i\)
#include <bits/stdc++.h>
using namespace std;
#define endl '\n'
#define inl inline
#define eb emplace_back
#define pii pair<int,int>
#define fi first
#define se second
#define getchar() cin.get()
#define int long long
const int N = 2e5 + 5;
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] , b[N] , ans;
int gcd ( int a , int b )
{
if ( a % b == 0 ) return b;
return gcd ( b , a % b );
}
int lcm ( int a , int b )
{
return a * b / gcd ( a , b );
}
signed main ()
{
ios::sync_with_stdio(false);
cin.tie(0) , cout.tie(0);
int T = read();
while ( T -- )
{
n = read();
ans = 1;
for ( int i = 1 ; i <= n ; i ++ ) a[i] = read() , b[i] = read();
int gcdd = a[1] * b[1] , lcmm = b[1];
for ( int i = 2 ; i <= n ; i ++ )
{
gcdd = gcd ( gcdd , a[i] * b[i] ) , lcmm = lcm ( lcmm , b[i] );
if ( gcdd % lcmm ) lcmm = b[i] , gcdd = a[i] * b[i] , ++ ans;
}
cout << ans << endl;
}
return 0;
}
Shocking Arrangement
首先判断特例:如果全是 \(0\) 显然无解
对于其余的情况 我们维护新数列的前缀和 如果这个前缀和大于 \(0\) 那么我们在负数中选一个数加进序列中 如果前缀和小于等于 \(0\) 那么塞进去一个正数即可
这样对于每一个前缀和 我们都能保证它的取值范围在 \([min_{a[i]},max_{a[i]}]\) 中间 那么任意两个前缀和相减的绝对值最大值就一定在 \(max_{a[i]}-min_{a[i]}\) 之内 所以符合条件
#include <bits/stdc++.h>
using namespace std;
#define endl '\n'
#define inl inline
#define eb emplace_back
#define pii pair<int,int>
#define fi first
#define se second
#define getchar() cin.get()
#define int long long
const int N = 3e5 + 5;
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] , b[N] , ans , flag , sum;
vector<int> zheng , fu;
signed main ()
{
ios::sync_with_stdio(false);
cin.tie(0) , cout.tie(0);
int T = read();
while ( T -- )
{
flag = 0 , sum = 0;
n = read();
zheng.clear() , fu.clear();
for ( int i = 1 ; i <= n ; i ++ ) flag |= ( a[i] = read() ) , a[i] >= 0 ? zheng.eb(a[i]) : fu.eb(a[i]);
if ( !flag ) { cout << "No" << endl; continue; }
cout << "Yes" << endl;
cout << zheng[zheng.size()-1] << ' ';
sum = zheng[zheng.size()-1];
zheng.pop_back();
for ( int i = 2 ; i <= n ; i ++ )
if ( sum > 0 ) cout << fu[fu.size()-1] << ' ' , sum += fu[fu.size()-1] , fu.pop_back();
else cout << zheng[zheng.size()-1] << ' ' , sum += zheng[zheng.size()-1] , zheng.pop_back();
cout << endl;
}
return 0;
}
Multitest Generator
显然 操作数最多为两次 因为我们对于任意序列 \([1,n]\) 都可以通过将 \(a_1\) 固定为 \(1\) 而将 \(a_2\) 改为 \(n-2\) 来满足条件
对于 \(0\) 次操作 我们可以记录 \(f[i]\) 数组表示以 \(i\) 为末尾的后缀能构成的 \(test\) 个数
那么转移方程不难得到:
第 \(i\) 位答案为 \(0\) 的充要条件就是 \(f_{i+1}\neq 0\) 且 \(a_i=f_{i+1}\)
如果答案不为 \(0\) 考虑两种情况:
- \(f_{i+1}\neq 0\),但是 \(a_i\neq f_{i+1}\)。
- \(f_{i+1}=0\)。
对于第一种情况,令 \(a_i\leftarrow f_{i+1}\) 即可,操作数为 \(1\)。
对于第二种情况,如果想要答案为 \(1\) 显然需要对 \(i+1\) 的后缀中的某一个数进行修改 使修改后 \(i+1\) 的后缀能构成 \(a_i\) 个 \(test\)
设 \(g_i\) 表示在 \(i\) 的后缀中进行一次修改后 能得到的最多 \(test\) 数
这个修改有两种情况:
- 修改 \(a_i\)。这意味着我们可以随意改变第一个 \(test\) 的长度,也就是这第一个 \(test\) 可以接在后面的任意一个状态的前面,这种情况能得到的最大值为 \(\max\limits_{j=i+1}^nf_j+1\)。
- 不修改 \(a_i\)。因为 \(a_{i+1}\) 到 \(a_{i+a_i}\) 之间的数会被 \(a_i\) 所在的 \(test\) 所包含,所以只有修改 \(i+a_i+1\) 的后缀中的某个数才能有贡献。因此这种情况能得到的最大值为 \(g_{i+a_i+1}+1\)。
那么 “ 对 \(i+1\) 的后缀中的某一个数进行修改后,\(i+1\) 的后缀能构成 \(a_i\) 个 \(test\) ” 的充要条件就是 \(g_{i+1}\ge a_i\) 之所以是大于等于号 是因为我们可以将前面的一次 \(1\) 操作或者 \(2\) 操作改为修改 \(a_i\) 来吃掉一些 \(test\)
剩下的情况答案就是 \(2\) 了
清数组要清到 \(n+1\) (?)
#include <bits/stdc++.h>
using namespace std;
#define endl '\n'
#define inl inline
#define eb emplace_back
#define pii pair<int,int>
#define fi first
#define se second
#define getchar() cin.get()
const int N = 3e5 + 5;
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] , ans[N] , f[N] , g[N] , fmaxx[N];
void init()
{
for ( int i = 1 ; i <= n + 1 ; i ++ ) f[i] = g[i] = ans[i] = fmaxx[i] = 0;
}
/*
3
7
3 1 3 1 2 1 1
4
1 2 1 7
4
2 7 1 1
*/
signed main ()
{
ios::sync_with_stdio(false);
cin.tie(0) , cout.tie(0);
int T = read();
while ( T -- )
{
n = read();
init();
for ( int i = 1 ; i <= n ; i ++ ) a[i] = read();
for ( int i = n ; i >= 2 ; i -- )
{
if ( i + a[i] == n ) f[i] = 1;
else if ( i + a[i] < n && f[i+a[i]+1] ) f[i] = f[i+a[i]+1] + 1;
fmaxx[i] = max ( f[i] , fmaxx[i+1] );
if ( i + a[i] >= n ) g[i] = fmaxx[i+1] + 1;
else g[i] = max ( fmaxx[i+1] , g[i+a[i]+1] ) + 1;
}
for ( int i = n - 1 ; i ; i -- )
{
if ( f[i+1] ) ans[i] = ( a[i] != f[i+1] );
else if ( g[i+1] >= a[i] ) ans[i] = 1;
else ans[i] = 2;
}
for ( int i = 1 ; i <= n - 1 ; i ++ ) cout << ans[i] << ' ';
cout << endl;
}
return 0;
}

浙公网安备 33010602011771号