先总结一下。

A竟然想了555分钟,同机房的人都切掉了之后才开始做。
B因为RE错了222次,罚了许多分;主要是看到WAWAWA,以为思路错了,事实上是数组开笑了。
C想了半天,无果。开DDD,切掉。
然后回到CCC,一个同机房的巨佬做出来之后,全机房的人问他怎么做;结果啥也没听懂,比赛结束后才恍然大悟。
用了自己的一个636636636分的,才打一场的灰名小号打,应该能上分吧……
Solution
A
对于每一对(i,j)(i,j)(i,j),配上(j,−i)(j,-i)(j,−i)即可。
B
开桶记录,乱搞即可。
C
首先,我加强一下数据: 可能有mmm个琴弦,m≤100000m≤100000m≤100000。
我们考虑贪心。首先,为了将可选的方案数量大幅减少,我们将这两个数组分别减去它们各自的最小值。可以发现,对于bbb中的一个数kkk,要么选择aaa中kkk的前驱,要么选择后驱。这可以用决策包容性来证明。
于是,我们在对aaa排序后,对于bbb中的每一个数通过二分找到aaa中它的前驱与后驱。记cic_ici表示bi−ajb_i-a_jbi−aj,did_idi表示bi−akb_i-a_kbi−ak,其中aja_jaj为aaa中bib_ibi的前驱,aka_kak为aaa中bjb_jbj的后驱。
我们将ccc从小到大排序,同时使ccc中的值与ddd中的值相对应。可以发现,对于每一个位置的配对,决策在ccc或ddd中;并且在最优解中,一定是前面一段先选择了ccc,后选择了ddd。
我们枚举这个位置,使得在这个位置及其之前选择了ccc,后面选择了ddd,即这个位置为差的最大值。至于差的最小值,为后面选择的ddd中的最小值,可以通过预处理后缀最小值来O(1)O(1)O(1)查询。我们求出每一对的差的最大值减去最小值,然后取minminmin即可。
总时间复杂度O(n(logn+logm)+mlogm)O(n(logn+logm)+mlogm)O(n(logn+logm)+mlogm)。
花絮: 一位机房巨佬Guess00赛时把这题切了,我们一起膜拜他吧! orz
D
一道水的构造题。
我们从后往前扫一遍,维护一个堆,记录下当前扫到的物品的从小到大排序的结果;每次取出堆顶作为当前这一次放进去的物品价值,并继续向前扫。
最后,我们再用相同的方式,使用一个堆,从前往后扫一遍,用来判断我们这种构造方案是否可行。如果可行直接输出方案,否则输出−1-1−1。
时间复杂度O(nlogn)O(nlogn)O(nlogn)。注意数组开大。
Code
A
#include <bits/stdc++.h>
#define int long long
using namespace std;
int t,n;
int a[200005];
signed main()
{
cin>>t;
while (t--)
{
cin>>n;
for (int i=1;i<=n;i++) cin>>a[i];
for (int i=1;i<=n;i++)
{
if (i%2==1) cout<<a[i+1]<<' ';
else cout<<-a[i-1]<<' ';
}
cout<<endl;
}
return 0;
}
B
#include <bits/stdc++.h>
#define int long long
using namespace std;
int t,n,m,x;
int a[1005][1005],v[1000005],num[1000005],ans[1005][1005];
signed main()
{
cin>>t;
while (t--)
{
cin>>n>>m;
for (int i=1;i<=n*m;i++) v[i]=num[i]=0;
for (int i=1;i<=n;i++)
{
for (int j=1;j<=m;j++) ans[i][j]=0;
}
for (int i=1;i<=n;i++)
{
cin>>a[i][1];
v[a[i][1]]=i;
for (int j=2;j<=m;j++) cin>>a[i][j];
}
for (int i=1;i<=m;i++)
{
for (int j=1;j<=n;j++)
{
cin>>x;
num[v[x]]=j;
}
}
for (int i=1;i<=n;i++)
{
for (int j=1;j<=m;j++) ans[num[i]][j]=a[i][j];
}
for (int i=1;i<=n;i++)
{
for (int j=1;j<=m;j++) cout<<ans[i][j]<<' ';
cout<<endl;
}
}
return 0;
}
C
//by gh
#include<bits/stdc++.h>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<cstdlib>
#define DEBUG cerr << "Passing Line " << __LINE__<< " in Function [" << __FUNCTION__ << "].\n";
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int INF = 0x3f3f3f3f;
const ll llINF = 1e18;
const int MAXN = 1e5 + 5;
const int MAXM = 10;
const int m = 6;
int n;
int a[MAXN],b[MAXN],suf[MAXN];
pii c[MAXN];
int main(){
// freopen("data.in","r",stdin);
// freopen("data.out","w",stdout);
for(int i = 1;i <= m;i++)
scanf("%d",&a[i]);
scanf("%d",&n);
for(int i = 1;i <= n;i++)
scanf("%d",&b[i]);
sort(a + 1,a + 1 + m);
sort(b + 1,b + 1 + n);
for(int i = 2;i <= m;i++)
a[i] -= a[1];
a[1] = 0;
for(int i = 2;i <= n;i++)
b[i] -= b[1];
b[1] = 0;
for(int i = 1;i <= n;i++){
int x = upper_bound(a + 1,a + 1 + m,b[i]) - a - 1;
c[i].first = b[i] - a[x];
x = lower_bound(a + 1,a + 1 + m,b[i]) - a;
if(x == m + 1)
c[i].second = -INF;
else
c[i].second = b[i] - a[x];
}
sort(c + 1,c + 1 + n);
int ans = INF;
suf[n] = c[n].second;
for(int i = n - 1;i >= 1;i--)
suf[i] = min(suf[i + 1],c[i].second);
for(int i = 1;i <= n;i++)
ans = min(ans,c[i].first - suf[i + 1]);
printf("%d\n",ans);
return 0;
}
D
#include <bits/stdc++.h>
#define int long long
using namespace std;
int n,pos=0,a[200005];
struct node
{
char x;
int num;
}tmp[200005];
signed main()
{
cin>>n;
for (int i=1;i<=2*n;i++)
{
cin>>tmp[i].x;
if (tmp[i].x=='-') cin>>tmp[i].num;
}
priority_queue<int,vector<int>,greater<int> > q;
for (int i=2*n;i>=1;i--)
{
if (tmp[i].x=='-')
{
int now=tmp[i].num;
q.push(now);
}
else
{
int x=q.top();
a[i]=x;
q.pop();
}
}
for (int i=1;i<=2*n;i++)
{
if (tmp[i].x=='+')
{
int now=tmp[i].num;
q.push(now);
}
else
{
int x=q.top();
if (tmp[i].num!=x) return cout<<"NO"<<endl,0;
q.pop();
}
}
cout<<"YES"<<endl;
for (int i=1;i<=2*n;i++)
{
if (a[i]) cout<<a[i]<<' ';
}
cout<<endl;
return 0;
}
本文分享了四道编程题目的解题思路与实现方法,包括构造题、贪心算法、排序与搜索等,提供了完整的代码示例及时间复杂度分析。
2148

被折叠的 条评论
为什么被折叠?



