Codeforces Round #679 (Div. 2, based on Technocup 2021 Elimination Round 1) 部分题解
Problem A
因为给的数组长度为偶数,所以每一项都和后一项抵消就好了。
Problem B
因为每个元素都是不一样的,所以我们只需要把行根据第一列的元素进行reorder就好了。
#include<bits/stdc++.h>
using namespace std;
const int maxn=510;
typedef long long ll;
void check_max (int &a,int b) { a=max (a,b);}
ll gcd(ll a,ll b){return b==0?a:gcd(b,a%b);}
ll lcm(ll a,ll b){return a/gcd(a,b)*b;};
map <int,int> mp;
set <int> s;
int n,m;
int v[maxn][maxn];
void solve () {
scanf ("%d%d",&n,&m);
mp.clear ();
s.clear ();
for (int i=1;i<=n;i++) {
for (int j=1;j<=m;j++) {
scanf ("%d",&v[i][j]);
if (j==1) {
mp[v[i][j]]=i;
s.insert (v[i][j]);
}
}
}
vector <int> cnt (n+1);
for (int j=1;j<=m;j++)
for (int i=1;i<=n;i++) {
int x;
scanf ("%d",&x);
if (s.count (x)) cnt[i]=mp[x];
}
// for (int i=1;i<=n;i++) printf ("%d ",cnt[i]);
for (int i=1;i<=n;i++) {
for (int j=1;j<=m;j++) {
printf ("%d ",v[cnt[i]][j]);
}
printf ("\n");
}
}
int main () {
int t;
scanf ("%d",&t);
while (t--) {
solve ();
}
return 0;
}
Problem C
首先暴力枚举肯定不行,偷鸡取各自最小值和最大值会wa on test7。考虑把每个数组对6个元素做差,并且放进一个vector中,值为他们所属的数组标号。接下来变成了在这个数组里面我们要得到一个差值最小并且子数组里面含有所以数组的一个子段。考虑离散化排序(排序也是十分重要的部分,可以想想看为什么)之后尺取,不离散的话没有办法发挥尺取的威力,过程中取min就好
了。
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+10;
const int inf=0x3f3f3f3f;
int n,a[6],b[maxn],cnt[maxn],id[maxn*6],x[maxn*6],sx[maxn*6];
vector <int> axis[maxn*6];
int main () {
for (int i=0;i<6;i++) scanf ("%d",a+i);
scanf ("%d",&n);
for (int i=0;i<n;i++) scanf ("%d",b+i);
int k=0;
for (int i=0;i<6;i++)
for (int j=0;j<n;j++) {
sx[k]=x[k]=b[j]-a[i];
id[k++]=j;
}
sort (x,x+k);
auto p=unique (x,x+k)-x;
for (int i=0;i<k;i++) {
sx[i]=lower_bound (x,x+p,sx[i])-x;
axis[sx[i]].push_back (id[i]);
}
int ans=INT_MAX,s=0,t=0,num=0;
while (1) {
while (t<p&&num<n) {
for (auto it:axis[t]) {
if (!cnt[it]) num++;
cnt[it]++;
}
t++;
}
if (num<n) break;
ans=min (ans,x[t-1]-x[s]);
for (auto it:axis[s]) {
--cnt[it];
if (!cnt[it]) --num;
}
s++;
}
printf ("%d\n",ans);
return 0;
}