cf(div1+div2)构造题:D. Bouncing Boomerangs
链接:https://codeforces.com/contest/1428/problem/D
(每列最多放2个,注意读题~)
从右边向左考虑,先说结论:
a[i]=0, 不放
a[i]=1,放在(i,i)
a[i]=2,(i,i)放一个点,然后后面找一个a[j]=1(j>i)的点(且之前没被其他a[i]=2的点使用过),然后把此时在(j,j)的点上升到(i,j)
a[i]=3,(i,i)放一个点,然后后面找一个没有没有放满的列(a[j]=1的话要求没有被a[i]=2的使用过),然后在(i,j)放一个点。
口胡一波为什么这样是对的:
我们看到回旋镖的轨迹,发现a[i]=3的其实是不好考虑的,因为可能跟我之前安插的点碰撞到,那么我们让a[i]=3的最后从(i,i)走,因为(i,i)是从右下到左上不断上升的,因此可以避免。
代码:
#include<bits/stdc++.h>
#define pii pair<int, int>
#define fi first
#define se second
#define mp make_pair
using namespace std;
const int maxn = 1e5+7;
int a[maxn];
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
int n;
cin >> n;
for(int i = 1; i <= n; i++) {
cin >> a[i];
}
int res = 0;
vector<pii > vec;
stack<pii > st; //a[i]=1
stack<int> st2; //没放满
bool flag = 1;
for(int i = n; i >= 1; i--) {
if(a[i] == 0) continue;
if(a[i] == 1) {
st.push(mp(i, i));
}
if(a[i] == 2) {
vec.push_back(mp(i, i));
st2.push(i);
res++;
if(!st.empty()) {
pii pp = st.top();
st.pop();
res++;
vec.push_back(mp(i, pp.fi));
}
else {
flag = 0; break;
}
}
if(a[i] == 3) {
vec.push_back(mp(i, i));
res++;
if(!st2.empty()) {
int tp = st2.top();
st2.pop();
vec.push_back(mp(i, tp));
res++;
st2.push(i);
continue;
}
if(!st.empty()) {
pii tp = st.top();
st.pop();
vec.push_back(mp(i, tp.fi));
vec.push_back(mp(tp.fi,tp.fi));
res+=2;
st2.push(i);
continue;
}
flag = 0;
break;
}
}
if(flag) {
while(!st.empty()) {
pii tmp = st.top();
st.pop();
vec.push_back(tmp);
res++;
}
cout << res << '\n';
for(auto it : vec) {
cout << it.fi << " " << it.se << '\n';
}
}
else {
cout << -1 << '\n';
}
}
顺丰集团工作强度 322人发布