Codeforces Round #552 (Div. 3)-1154E-Two Teams-(模拟+双指针)

http://codeforces.com/contest/1154/problem/E

解题:

举例n=10,k=1

1,2,10,4,7,6,9,8,5,3

第一次,1队先挑2,10,4这三个人

1,2,10,4,7,6,9,8,5,3

第二次,2队挑6,9,8三个人

1,2,10,4,7,6,9,8,5,3

第三次,1队挑1,7,5三个人

1,2,10,4,7,6,9,8,5,3

第四次,2队挑3一个人

1,2,10,4,7,6,9,8,5,3

显然需要实现的有两点

(1)挑完后的“连接”,比如

第一次挑完后需要把1和7“连接”起来

第二次挑完后需要把7和5“连接”起来

用l数组标记当前下标 左边相邻的数的下标

用r数组标记当前下标 右边相邻的数的下标

例如一开始:

r[1]=2,表示下标为1的人(1)的右边是下标为2那个人(2)

l[5]=4,表示下标为5的人(7)的左边是下标为3那个人(4)

第一次挑完之后

r[1]=5,表示下标为1的人(1)的右边是下标为5那个人(7)

l[5]=1,表示下标为5的人(7)的左边是下标为1那个人(1)

每次挑完人后把已经挑选的人“删掉”,左右扩散找人可以通过左右数组来找人,直接跳过被挑选过的人,实现“删掉”,

(2)快速找最大值,暴力寻找肯定会超时

一般遇到n个不同的数随机出现在数组里,可以用下标数组idx标记这个数出现的下标位置,直接查找。

dix[10]=3表示10这个数在原数组的下标位置是3

这里可以从n开始减小,一直减到1,时间复杂度O(n)

#include<stdio.h>
#include<math.h>
#include<string.h>
#include<algorithm>
#include<string>
#include<vector>
#include<iostream>
#include<cstring>
#include<set>
#include<queue>
#define inf 0x3f3f3f3f
#define ll long long
using namespace std;

int n,k,maxxidx,maxx;
int a[200005];
int l[200005];///下标为i的人 的左边 下标是多少
int r[200005];///下标为i的人 的右边 下标是多少
int idx[200005];///标记原数组下标
int ans[200005];

void findmax()///找最大值,主要是改变全局变量maxxidx和maxx
{
    while(maxx>=1)
    {
        if( ans[ idx[maxx] ]==0 )
        {
            maxxidx=idx[ maxx ];
            break;
        }
        maxx--;
    }
}

int main()
{
    while(scanf("%d%d",&n,&k)!=EOF)
    {
        memset(a,0,sizeof(a));
        memset(l,0,sizeof(l));
        memset(r,0,sizeof(r));
        memset(idx,0,sizeof(idx));
        memset(ans,0,sizeof(ans));
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&a[i]);
            idx[ a[i] ]=i;
            l[i]=i-1;
            r[i]=i+1;
        }
        l[n+1]=n;
        r[0]=1;
        maxxidx=idx[n];///初始化为最大的下标
        maxx=n;
        int now=0;///当前已经选了多少人
        int t=1;///初始是1队先挑人
        while(now<n)
        {
            findmax();
            int i=maxxidx;///最大的那个人的下标
            ans[i]=t;
            now++;
            int x=l[i];
            int y=r[i];///中间向左右两边扩展
            for(int j=1;j<=k;j++)
            {
                if(x>=1 && x<=n)///如果x是0表明左边无人了
                    ans[x]=t,x=l[x],now++;///通过左右指针数组找下一个人
                if(y>=1 && y<=n)
                    ans[y]=t,y=r[y],now++;
            }
            ///挑完人就该改左右下标了
            l[y]=x;
            r[x]=y;
            if(t==1)
                t=2;
            else
                t=1;
        }
        for(int i=1;i<=n;i++)
            printf("%d",ans[i]);
        printf("\n");
    }
    return 0;
}

原文地址:https://www.cnblogs.com/shoulinniao/p/10840491.html

时间: 2024-10-04 13:16:36

Codeforces Round #552 (Div. 3)-1154E-Two Teams-(模拟+双指针)的相关文章

Codeforces Round #273 (Div. 2) B . Random Teams 贪心

B. Random Teams n participants of the competition were split into m teams in some manner so that each team has at least one participant. After the competition each pair of participants from the same team became friends. Your task is to write a progra

Codeforces Round #552 (Div. 3) C题

题目网址:http://codeforces.com/contest/1154/problem/C 题目意思:小猫吃三种食物,A,B,C,一周吃食物的次序是,A,B,C,A,C,B,A,当小猫该天无食物可吃时,就会饿死,现给出a,b,c三个数,表示A,B,C的食物数量, 选择一天开始,问小猫最多可以活到多少天. 题解:首先,在一周时间,A要吃三天,B要吃两天,C要吃两天,先随便选一天开始,当剩下食物不足以撑过一周时停止,再细分剩下的食物数量,看小猫饿 死是经过的最多天数.选择的天数用暴力写即可.

Codeforces Round #552(div.3)

Problem: http://codeforces.com/contest/1154 A: 1 /* basic header */ 2 #include <iostream> 3 #include <cstdio> 4 #include <cstdlib> 5 #include <string> 6 #include <cstring> 7 #include <cmath> 8 #include <cstdint> 9

Codeforces Round #552 (Div. 3) Editorial 1154C - Gourmet Cat

链接:https://codeforces.com/contest/1154/problem/C 题意:一只旅行的小猫在特定的星期里吃特定的食物,一四七a,二六b,三五c,现在给三种食物的数量,问小猫最多能活几天. 思路:先看小猫能活几个整星期,因为a在一个星期里占三天,b和c各占两天,所以取min(a/3,b/2,c/2),然后求剩下的,这个时候就可以枚举日子了,从周一枚举到周日,然后模拟一哈就行了,虽然是个水题但我还是没做粗来 代码: 1 //#include<bits/stdc++.h>

Codeforces Round #552 (Div. 3) E C++

题目: E. Two Teams time limit per test 2 seconds memory limit per test 256 megabytes input standard input output standard output There are nn students standing in a row. Two coaches are forming two teams — the first coach chooses the first team and the

Codeforces Round #552 (Div. 3)-D-Walking Robot-(贪心)

http://codeforces.com/contest/1154/problem/D 解题: 1.无光的时候优先使用太阳能电池. 2.有光的时候 (1)太阳能电池没满电,让它充,使用普通电池 (2)太阳能电池满电,使用太阳能电池 #include<stdio.h> #include<math.h> #include<string.h> #include<algorithm> #include<string> #include<vecto

Codeforces Round #246 (Div. 2) A. Choosing Teams

给定n k以及n个人已参加的比赛数,让你判断最少还能参加k次比赛的队伍数,每对3人,每个人最多参加5次比赛 #include <iostream> using namespace std; int main(){ int n,k, cnt = 0; cin >> n >> k; for(int i = 0 ; i < n; ++ i){ int a; cin >> a; if(a+k <= 5) cnt ++; } cout<<cnt

Codeforces Round #316 (Div. 2)C. Replacement(模拟)

传送门 Description Daniel has a string s, consisting of lowercase English letters and period signs (characters '.'). Let's define the operation of replacement as the following sequence of steps: find a substring ".." (two consecutive periods) in st

Codeforces Round #315 (Div. 2) 569A Music (模拟)

题目:Click here 题意:(据说这个题的题意坑了不少人啊~~~)题目一共给了3个数---- T 表示歌曲的长度(s).S 表示下载了歌曲的S后开始第一次播放(也就是说S秒的歌曲是事先下载好的).q 表示下载速度(每秒下载歌曲(q-1)/q秒).问题就是播放的速度比下载的速度慢,每当播放到没下载的位置,就会重新从头播放,输出的就是从头播放的次数(包括第一次). 分析:高中物理追击问题,模拟下好了. 1 #include <bits/stdc++.h> 2 using namespace