第一次打Div2,对我来说还是很难,写篇博客记录一下~
A题
题意:T组输入,每组输入一个n,m,代表nm大小的地板,以1k大小的地砖完全覆盖地板(k>=2,且同一地板中k可以不同)。将水平放置的地砖与垂直放置的地砖相减的值定义为稳定性,求最大的稳定性是多少。
思路:
尽可能的使得水平放置的地砖多,垂直放置的地砖少,且地砖的总数尽可能多。
地砖总数尽可能多可以通过仅使用12大小的地砖实现,水平放置的地砖尽可能多可以通过先一直放置水平地砖,无法放置了再放垂直地砖实现。
但,真的有放置垂直地砖的需要吗?由于我们一直使用的是12大小的地砖来保证地砖总数尽可能多,但如果列数m是一个奇数就会有一列无法填补完全需要使用垂直的砖块。但题目给出地砖的大小可以为不同,因此我们可以在最后一列无法填补时将将最后一块砖换成1*3大小的刚好将最后一列填上,这样就能保证砖头总数最多的同时垂直放置的地砖最少。
代码:
int main()
{
int t;
cin>>t;
while(t--)
{
int n,m;
cin>>n>>m;
int k=m/2;
cout<<n*k<<"\n";
}
return 0;
}
B题
题意:给出一个n和两个长度为n的序列a,b。a,b中的值为1~n,且序列中元素不重复。有一种可以进行无限次的操作,选择一对(i,j),同时将(a[i],a[j])与(b[i],b[j])交换。当i<j时,若a[i]>a[j],则认为(i,j)是倒置的,要求求出a,b序列经操作后倒置对数最少的可能。
思路:
先将a序列排序,再考虑减少b序列中的倒置对数。
将a序列排完序后发现,此时如果将a序列中任意一对数交换,则a序列一定会多出一对倒置的数,而b序列却不一定减少倒置的数,若减少倒置的数也仅会减少一对。
如:
a序列:{1,2,3,4,5}
b序列:{5,2,4,3,1}
将a序列的(4,5)交换,a序列多出一对倒置对数,将b序列(3,1)交换,b序列倒置对数不变,总体多了一对倒置对数。因此,将a序列从小到大排完序后的结果就是答案。
代码:
const int N=2e5+10;
int t,n;
int b[N];
struct node
{
int x,y;
}a[N];
bool cmp(node x,node y)
{
return x.x<y.x;
}
int main()
{
cin>>t;
while(t--)
{
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>a[i].x;
a[i].y=i;
}
for(int i=1;i<=n;i++)
{
cin>>b[i];
}
sort(a+1,a+n+1,cmp);
for(int i=1;i<=n;i++)
{
cout<<a[i].x<<" \n"[i==n];
}
for(int i=1;i<=n;i++)
{
cout<<b[a[i].y]<<" \n"[i==n];
}
}
return 0;
}
C题
题意:给出一个a,b,r,求出|((a ^ x)-(b ^ x))|(0<=x<=r)的最小值。
思路:按位计算贡献。
很明显当a与b的第i位都是0或1时,那么无论怎么异或都不会对结果产生影响,即贡献为0。
如: a=2,b=2时;
a的二进制为 10
b的二进制为 10
当x也为2时,1 ^ 1 = 0,0 ^ 0 = 0,a ^ x = 0,b ^ x = 0,a-b=0。
当x为0时,1 ^ 0 = 1,0 ^ 0 = 0,a ^ x = 2,b ^ x = 2,a - b = 0。
因此我们仅需要考虑a与b第i位不相等的情况。
当a的第i位为1,b的第i位位0时,就会产生2的i次贡献,当a的第i位为0,b的第i位为1时,就会产生负的2的i次的贡献。
如: a=5,b=3时
a的二进制为 1 0 1
b的二进制为 0 1 1
贡献 4 -2 0
总的贡献为2,即在不进行操作的情况下差值为2。
而若进行操作使得贡献最小,很明显应该将a,b每一位的贡献转换为正+负+负……或负+正+正……
如:
a为 1 1 1 0 1
b为 0 0 1 0 1
贡献 16 8 0 0 0
显然将贡献为8的那一位转换为-8能够得到最小的贡献。
然而,x的取值范围必须小于等于r,因此,我们还需要一点点的贪心,使得x尽可能将贡献和减小。
代码:
#include <bits/stdc++.h>
#define ios \
ios::sync_with_stdio(false); \
cin.tie(0); \
cout.tie(0)
using namespace std;
int add(int x, int y) { return x ? add((x & y) << 1, x ^ y) : y; }
#define ONLINE_JUDGE
typedef long long ll;
int t;
int main()
{
#ifndef ONLINE_JUDGE
freopen("1.in", "r", stdin);
freopen("1.out", "w", stdout);
#endif
ios;
cin >> t;
while (t--)
{
ll a, b, r;
cin >> a >> b >> r;
bool flag = true;
ll now = 0;
for (ll i = 60; i >= 0; i--)
{
bool x = (a & (1LL << i));
bool y = (b & (1LL << i));
if (x == y)
{
continue;
}
if (flag)
{
now = (1LL << i) * (x - y);
flag = false;
}
else
{
if (r >= (1LL << i) && (x - y) * now > 0)
{
r -= (1LL << i);
now -= (x - y) * (1LL << i);
}
else
{
now += (x - y) * (1LL << i);
}
}
}
if (now > 0)
{
cout << now << "\n";
}
else
{
cout << -now << "\n";
}
}
return 0;
}
标签:地砖,倒置,int,Codeforces,贡献,放置,序列,922,Round
From: https://www.cnblogs.com/Aliciaandsakura/p/17998487