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';
    }
}
全部评论

相关推荐

在评审的大师兄很完美:像这种一般就是部门不匹配 转移至其他部门然后挂掉 我就是这样被挂了
点赞 评论 收藏
分享
孤寡孤寡的牛牛很热情:为什么我2本9硕投了很多,都是简历或者挂,难道那个恶心人的测评真的得认真做吗
点赞 评论 收藏
分享
联通 技术人员 总包不低于12
点赞 评论 收藏
分享
3 收藏 评论
分享
牛客网
牛客企业服务