Codeforces 1154E.Two Teams(思维,两个set 直接艹)

Two Teams

题目链接:点我看题

题意: n n n 个人有编程能力 a i a_i ai,排成一行。两个教练 A A A B B B,教练 A A A 先手,每一次选这一行中的最大编程能力的人,然后再向左右两选取 k k k 个人,不足 k k k 个则全部选取,选取了的人就离开。然后教练 B B B 做相同的操作。 输出 最后每个人属于的教练, A A A输出 1 1 1 B B B 输出 2 2 2.

思路:

  • 考虑到每次都需要最大值,可以用 s e t set set 维护一个结构体(含 i d id id a [ i ] a[i] a[i]),按 a [ i d ] a[id] a[id] 从大到小重载运算符,那么每次提取都是提取 b e g i n ( ) begin() begin()
  • 对于两边的 k k k 个人,同样的用 s e t set set 维护结构体,和上面的一样,重载是按 i d id id 从小到大,每一次都 l o w e r _ b o u n d lower\_bound lower_bound 获取 当前最大值的 i d id id 在 此 s e t set set 中的迭代器位置,然后分别往前、往后遍历,记录答案,删除即可。
  • !!!值得注意的是:需要先存起来,然后删除,因为删除的同时,遍历,迭代器会变
  • 具体细节最好看代码

Code:

#include<bits/stdc++.h>
#define debug(x) cout << "[" << #x <<": " << (x) <<"]"<< endl
#define pii pair<int,int>
#define clr(a,b) memset((a),b,sizeof(a))
#define rep(i,a,b) for(int i = a;i < b;i ++)
#define pb push_back
#define MP make_pair
#define LL long long
#define ull unsigned LL
#define ls i << 1
#define rs (i << 1) + 1
#define fi first
#define se second
#define ptch putchar
#define CLR(a) while(!(a).empty()) a.pop()

using namespace std;
inline LL read() {
    LL s = 0,w = 1;
    char ch = getchar();
    while(!isdigit(ch)) {
        if(ch == '-') w = -1;
        ch = getchar();
    }
    while(isdigit(ch))
        s = s * 10 + ch - '0',ch = getchar();
    return s * w;
}
inline void write(LL x) {
    if(x < 0)
        putchar('-'), x = -x;
    if(x > 9)
        write(x / 10);
    putchar(x % 10 + '0');
}
#ifndef ONLINE_JUDGE
    clock_t prostart = clock();
#endif

const int maxn = 2e5 + 10;
int a[maxn];
struct xx{
    int id,maxx;
    bool operator < (const xx &A) const{
        return A.maxx < maxx;
    }
};
set<xx> se;
struct node{
    int id,maxx;
    bool operator < (const node &A) const{
        return id < A.id;
    }
};
set<node> have;
int ans[maxn];

int main() {
#ifndef ONLINE_JUDGE
//    freopen("in.txt", "r", stdin);
//    freopen("out.txt", "w", stdout);
#endif

    int n = read(),k = read();
    for(int i = 1;i <= n;++ i){
        a[i] = read();
        se.insert(xx{i,a[i]});
        have.insert(node{i,a[i]});
    }
    int who = 1;
    vector<int> v;
    while(!se.empty()){
        v.clear();
        int id = se.begin() -> id;
        ans[id] = who;
        se.erase(xx{id,a[id]});
        auto pos = have.lower_bound(node{id,a[id]});
        auto tmp = pos; ++ tmp;
        int coun = 0;
        while(tmp != have.end() && coun < k){
            ans[tmp -> id] = who;
            v.pb(tmp -> id);
            ++ tmp; ++ coun;
        }
        for(int i = 0;i < v.size();++ i){
            have.erase(node{v[i],a[v[i]]});
            se.erase(xx{v[i],a[v[i]]});
        }

        v.clear();
        coun = 0;
        pos = have.lower_bound(node{id,a[id]});
        tmp = pos;
        if(tmp != have.begin()){
            -- tmp;
            while(tmp != have.begin() && coun < k){
                ans[tmp -> id] = who;
                v.pb(tmp -> id);
                -- tmp; ++ coun;
            }
            if(coun < k){
                ans[have.begin() -> id] = who;
                v.pb(have.begin() -> id);
            }
            for(int i = 0;i < v.size();++ i){
                have.erase(node{v[i],a[v[i]]});
                se.erase(xx{v[i],a[v[i]]});
            }
        }

        have.erase(node{id,a[id]});
        who = who == 1 ? 2 : 1;
    }
    for(int i = 1;i <= n;++ i)
        write(ans[i]);
    ptch('\n');

#ifndef ONLINE_JUDGE
    cout << "time: " << 1.0 * (clock() - prostart) / CLOCKS_PER_SEC << " s" << endl;
#endif
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值