Codeforces Round 1024 (Div. 2) A-D
感觉前三题比较拼手速的一场
前两题wa了3发,扣分爆了
D题赛时的思路虽然对但有点复杂,不想自己写逆序对,遂从网上随便抄了个逆序对的板子。
赛时一直在wa,红温了两小时,第二天才发现是抄的板子有问题。
让ai写了个归并排序逆序对板子,一发过了
A. Dinner Time
可能有一点点难想的签
当数组刚好能放下几个长度是p的序列时,则必须保证这些p的总和是m
否则,可以让最后 n%p 个数的值,总和等于 m - 前面的几个p,然后从后往前填数即可
赛事没过脑子wa了一发
点击查看代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
using pii=pair<int,int>;
using ll=long long;
// using lll=__int128;
using ull=unsigned long long;
const ll inf=1e18;
const int mod =1e9+7;
void solve(){
int n,m,p,q;
cin>>n>>m>>p>>q;
if((n%p)==0){
int cnt=n/p;
if(cnt*q==m) cout<<"YES\n";
else cout<<"NO\n";
}
else{
cout<<"YES\n";
}
}
signed main(){
ios::sync_with_stdio(0);
cin.tie(0);
int ct=1;
cin>>ct;
while(ct--){
solve();
}
return 0;
}
B. The Picky Cat
枚举a[1]和 -a[1]两个数作为中位数即可,如果可以严格有n/2个比a[1]大的数,则满足条件。
for循环一遍记数即可
点击查看代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
using pii=pair<int,int>;
using ll=long long;
// using lll=__int128;
using ull=unsigned long long;
const ll inf=1e18;
const int mod =1e9+7;
void solve(){
int n;
cin>>n;
int cnt=0;//比a[i]大的数
vector<int> a(n+1);
for(int i=1;i<=n;i++){
cin>>a[i];
if(a[i]>a[1]) cnt++;
}
//如果可以严格有n/2个比a[1]大的数,则可以
for(int i=1;i<=n;i++){
if(cnt==n/2){
cout<<"YES\n";
return;
}
if(a[i]>a[1] && cnt>n/2 && a[i]*(-1)<a[1]) cnt--;
if(a[i]<a[1] && cnt<n/2 && a[i]*(-1)>a[1]) cnt++;
if(cnt==n/2){
cout<<"YES\n";
return;
}
}
cnt=0;
a[1]*=-1;
for(int i=1;i<=n;i++){
if(a[i]>a[1]) cnt++;
}
for(int i=1;i<=n;i++){
if(cnt==n/2){
cout<<"YES\n";
return;
}
if(a[i]>a[1] && cnt>n/2 && a[i]*(-1)<a[1]) cnt--;
if(a[i]<a[1] && cnt<n/2 && a[i]*(-1)>a[1]) cnt++;
if(cnt==n/2){
cout<<"YES\n";
return;
}
}
cout<<"NO\n";
}
signed main(){
ios::sync_with_stdio(0);
cin.tie(0);
int ct=1;
cin>>ct;
while(ct--){
solve();
}
return 0;
}
C. Mex in the Grid
显然要让更小的数更靠近中间(要让更小的数被更多矩形覆盖)
因为如果一个矩形里没有某个数,则这个矩形的mex最大就是这个数。所以要让较小的数被更多矩形覆盖
代码可能有一点点不太好写
点击查看代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
using pii=pair<int,int>;
using ll=long long;
// using lll=__int128;
using ull=unsigned long long;
const ll inf=1e18;
const int mod =1e9+7;
void solve(){
int n;
cin>>n;
int g[n+10][n+10];
int x=(n-1)/2,y=(n-1)/2;
int now=0;
g[x][y]=now++;
int mx=n*n;
int cnt=1;
while(now<mx){
for(int i=0;i<cnt && now<mx;i++){
y++;
if(x>=0 && x<n && y>=0 && y<n){
g[x][y]=now++;
}
}
for(int i=0;i<cnt && now<mx;i++){
x++;
if(x>=0 && x<n && y>=0 && y<n){
g[x][y]=now++;
}
}
cnt++;
for(int i=0;i<cnt && now<mx;i++){
y--;
if(x>=0 && x<n && y>=0 &&y<n){
g[x][y]=now++;
}
}
for(int i=0;i<cnt && now<mx;i++){
x--;
if(x>=0 && x<n && y>=0 &&y<n){
g[x][y]=now++;
}
}
cnt++;
}
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
cout<<g[i][j]<<" ";
}
cout<<endl;
}
}
signed main(){
ios::sync_with_stdio(0);
cin.tie(0);
int ct=1;
cin>>ct;
while(ct--){
solve();
}
return 0;
}
D. Quartet Swapping
首先有个很显然的想法,可不可以,直接分别对奇数位和偶数位排序就行。
但是本题的交换操作是对连续四个数进行交换
发现,每次交换,会让奇数位和偶数位分别增加或减少一个逆序对。
所以,无论怎么操作,奇数位和偶数位的逆序对个数的和的奇偶性不变。
现在得到结论1:奇数位的逆序对个数和偶数位的逆序对个数的和 奇偶性保持不变
现在在思考操作序列,假设a,b,c,d,e,ace在奇数位,bd在偶数位
从前往后操作,在第1位时,一定能把奇数位的最小值挪到这里。
在第2位(n-3)时,一把偶数位的最小值挪过来。
所以,除了 n-2,n-1,n,其他位置都会是递增的。
而n-1(d),在偶数位,因为前面的偶数位已经排好序且一定大于这一位的数,所以第n-1位也是有序的
所以不确定的位置只有n-2和n位
而如果这两位是有序的,则逆序对的和是0,否则逆序对的和是1 (结论2)
根据结论1,逆序对和的奇偶性不变,所以如果是奇数(1),就让n-2 > n即可,否则n-2<n
归并排序或树状数组统计逆序对个数即可
点击查看代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
using pii=pair<int,int>;
using ll=long long;
// using lll=__int128;
using ull=unsigned long long;
const ll inf=1e18;
const int mod =1e9+7;
int countInversePairs(vector<int>& nums) {
int n = nums.size();
if (n < 2) return 0;
vector<int> temp(n);
auto merge = [&](auto merge, int l, int r) -> int {
if (l >= r) return 0;
int m = l + (r - l) / 2;
int cnt = 0;
cnt += merge(merge, l, m);
cnt += merge(merge, m + 1, r);
int i = l, j = m + 1, k = l;
while (i <= m && j <= r) {
if (nums[i] <= nums[j]) {
temp[k++] = nums[i++];
} else {
temp[k++] = nums[j++];
cnt += (m - i + 1);
}
}
while (i <= m) temp[k++] = nums[i++];
while (j <= r) temp[k++] = nums[j++];
for (int p = l; p <= r; ++p) nums[p] = temp[p];
return cnt;
};
return merge(merge, 0, n - 1);
}
void solve(){
int n;
cin>>n;
vector<int> t1,t2,a(n+10);
int p1,p2;
for(int i=1;i<=n;i++){
cin>>a[i];
if(i&1) t1.push_back(a[i]);
else t2.push_back(a[i]);
}
int cnt1=countInversePairs(t1);
int cnt2=countInversePairs(t2);
sort(t1.begin(),t1.end(),greater<>());
sort(t2.begin(),t2.end(),greater<>());
vector<int> ans;
ans.push_back(-1);
for(int i=1;i<=n;i++){
if(i&1){
ans.push_back(t1.back());
t1.pop_back();
}
else{
ans.push_back(t2.back());
t2.pop_back();
}
}
// cout<<cnt1<<" "<<cnt2<<endl;
if((cnt1&1)!=(cnt2&1)){
swap(ans[ans.size()-1],ans[ans.size()-3]);
}
for(int i=1;i<=n;i++){
cout<<ans[i]<<" ";
}
cout<<endl;
}
signed main(){
ios::sync_with_stdio(0);
cin.tie(0);
int ct=1;
cin>>ct;
while(ct--){
solve();
}
return 0;
}

浙公网安备 33010602011771号