传送门:https://codeforces.com/contest/1998
目录
A. Find K Distinct Points with Fixed Center
B. Minimize Equal Sum Subarrays
C. Perform Operations to Maximize Score
D. Determine Winning Islands in Race
A. Find K Distinct Points with Fixed Center
题意:
反思:赛时没考虑到不同的组必须不同(赛时AC,但赛后被hack)
错解:
void solve()
{
int x , y , k;
cin >> x >> y >> k;
int sum1 = 0 , sum2 = 0;
for(int i = 1 ; i <= k - 1; i++)
{
sum1 += i; sum2 += i;
cout << i << " " << i << endl;
}
cout << k * x - sum1 << " " << k * y - sum2 << endl;
// 最后的解可能与之前的解相等
}
思路:(构造题)
对称的思想
1. 当 k 为偶数时 ( x - 1 , y - 1 ) , ( x + 1 , y + 1 ) ......
2. 当k为奇数时 ( x - 1 , y - 1 ) , ( x + 1 , y + 1 ) ..... ( x , y )
代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define int long long
void solve()
{
int x , y , k;
cin >> x >> y >> k;
for( int i = 1 ; i <= k / 2; i++)
{
cout << x - i << " " << y - i << endl;
cout << x + i << " " << y + i << endl;
}
if( k & 1 )cout << x << " " << y << endl;
}
signed main()
{
int tt = 1;
cin >> tt;
while(tt--)solve();
return 0;
}
B. Minimize Equal Sum Subarrays
题意:
思路:构造题
1. 当 x < n 时 , x++
2. 当 x == n 时,x = 1
配对数始终为1
代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define int long long
const int N = 1e6 + 10;
const int mod = 1e9 + 7;
const int INF = 0x3f3f3f3f;
int a[N];
int sum[N];
void solve()
{
int n;
cin >> n;
for( int i= 1; i<= n ; i++)
{
int x ; cin >> x;
if( x == n )cout << 1 << endl;
else cout << x + 1 << endl;
}
cout << endl;
}
signed main()
{
int tt = 1;
cin >> tt;
while(tt--)solve();
return 0;
}
C. Perform Operations to Maximize Score
题意:
给定 有 n 个元素的数组 a , b 和整数 k , 最多可以执行 k 次操作(操作为选择索引 i , 当b[i] == 1 时,可以将对应的a[i]++ , 求 max + median 的最大值)
思路:
1 . 一直加到某个数上,从而改变最大值
2. 分开加到某个数上 , 此时有两种情况
最大值改变 或 中位数改变 ,这种情况的最优解 <= 1
中位数改变,二分答案最大中位数
代码:
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N = 2e5 + 10;
typedef pair<int, int> pii;
pii a[N]; int n, k;
bool check(int x)
{
int cnt = 0;
vector<int> b;
for (int i = 1; i <= n - 1; i++)
{
if (a[i].first >= x)cnt++;
else if( a[i].second == 1 ) b.push_back(x - a[i].first);
}
reverse(b.begin(), b.end());
x = k;
for (auto e : b)
{
if (x >= e) {
cnt++;
x -= e;
}
}
return cnt >= ( n + 1 ) / 2 ;
}
void solve()
{
cin >> n >> k;
for (int i = 1; i <= n; i++)
cin >> a[i].first;
for (int i = 1; i <= n; i++) cin >> a[i].second;
sort(a + 1, a + n + 1);
int ans = 0;
// 改变最大值 ,一直加到某个数上
for (int i = 1; i <= n; i++)
{
if (a[i].second == 1)
{
int mc = 0;
if (i <= n / 2)mc = a[n / 2 + 1].first;
else mc = a[n / 2].first;
ans = max(ans, a[i].first + mc + k);
}
}
int left = 0;
int right = 1e9;
// 枚举中位数
while (right > left)
{
int mid = left + right + 1 >> 1;
if (check(mid)) left = mid;
else right = mid - 1;
}
ans = max(ans, a[n].first + left);
cout << ans << endl;
}
signed main()
{
int tt;
cin >> tt;
while (tt--)solve();
return 0;
}
D. Determine Winning Islands in Race
题意:
有 A , B 两人,A可以走主桥和备用桥 , B只能走备用桥,给定 n 个岛屿和 m 条备用桥,到达第n个岛屿获胜,当一个人离开岛屿后,这座岛屿和连接的所有桥都将倒塌,若 B 可以从 i ( 1 <= i <= n - 1 )岛屿先出发,如果从 i 岛屿出发能够获胜,则输出1 ,否则输出0
思路:
若要 B 输 ,则到达某个岛屿之前 A 先到达 ,因为 A 只能从 1 号岛屿出发,若要抢先到达,肯定需要走备用桥,假设备用桥 沟通 i , j A 的出生地为 loc
则有 loc >= i + 1 && j - loc > t[i] + 1
可以求出 loc 的范围 [ i + 1 , j - t[i] - 2 ] , 也就是 当 loc 属于此范围必输
则可以枚举每一个备用桥,求出 loc 的范围
设 loc 并起来的总范围是 K
A 能够获胜的区间是 [ 1 , n - 1] - K
我们在维护总范围时,可以使用差分 让ans[ i + 1]++ , ans[ j - t[i] - 1]--
[ i + 1 , j - t[i] -2 ] 的前缀和 > 0不符合题意 , 此区间外前缀和 均等于 0
#include<bits/stdc++.h>
using namespace std;
const int N = 4e5 + 10;
int h[N] , e[N] , ne[N] , idx;
int dist[N];
void add( int a , int b)
{
e[idx] = b;
ne[idx] = h[a];
h[a] = idx++;
}
void solve()
{
int n , m;
cin >> n >> m;
for( int i = 1 ;i <= n ;i++)h[i] = -1;
for( int i= 1; i<= n;i++)dist[i] = 0x3f3f3f3f;
idx = 0;
for( int i = 1 ;i < n; i++)add( i , i + 1 );
for( int i = 0 ;i < m; i++)
{
int a, b;
cin>> a>>b;
add( a , b );
}
queue<int> que;
que.push(1);
dist[1] = 0;
while(que.size())
{
auto t = que.front();
que.pop();
for( int i = h[t] ; i != -1 ; i = ne[i] )
{
int j = e[i];
if( dist[j] > dist[t] + 1 )
{
dist[j] = dist[t] + 1;
que.push(j);
}
}
}
vector<int> ans( n + 1 , 0 );
for( int i = 1; i < n; i++)
{
for( int j = h[i] ; j != -1 ; j = ne[j] )
{
int k = e[j];
if( i + 1 <= k - dist[i] - 2 ){
ans[i+1]++;
ans[k-dist[i]-1]--;
}
}
}
for( int i = 1 , sum = 0 ; i < n ;i++)
{
sum += ans[i];
if( sum == 0 )cout << 1;
else cout << 0;
}
cout << endl;
idx = 0;
}
int main()
{
int _;
cin >> _;
while(_--)solve();
return 0;
}