CF - 420B - Online Meeting(思维)

题意:n 个人參加线上会议。某经理记录了中间一段时间的 m 条上下线记录(1?≤?n,?m?≤?105)。+ 表示上线,- 表示下线。

leader是指仅仅要有人在线,他都在线的人。求全部可能的leader。

题目链接:http://codeforces.com/problemset/problem/420/B

——>>这种一种人,他们在记录中的第一条记录是下线的,定义为xx。。

三个断言:

1)假设xx存在。那么出现的人中,leader仅仅可能是最后出现的那个xx。。

2)假设xx不存在,那么出现的人中,leader仅仅可能是第一个登录的人。。

3)没出现过的人都能够是leader。

#include <cstdio>
#include <set>

using std::set;

const int MAXN = 100000 + 10;

int n, m;
char op[MAXN];
int p[MAXN];
int sum, leader;
int firstPlus = -1, lastInfinite = -1;
bool vis[MAXN];

void Init()
{
    sum = n;
    for (int i = 1; i <= n; ++i)
    {
        vis[i] = true;
    }
}

void Read()
{
    for (int i = 1; i <= m; ++i)
    {
        getchar();
        scanf("%c%d", op + i, p + i);
        if (op[i] == ‘-‘ && vis[p[i]] == true)
        {
            lastInfinite = p[i];
        }
        if (firstPlus == -1 && op[i] == ‘+‘)
        {
            firstPlus = p[i];
        }
        if (vis[p[i]])
        {
            vis[p[i]] = false;
            --sum;
        }
    }
}

void Solve()
{
    set<int> se;

    leader = lastInfinite == -1 ?

firstPlus : lastInfinite;
    if (lastInfinite != -1)
    {
        se.insert(leader);
    }
    for (int i = 1; i <= m; ++i)
    {
        if (op[i] == ‘+‘)
        {
            se.insert(p[i]);
            if (se.find(leader) == se.end())
            {
                leader = -1;
                break;
            }
        }
        else
        {
            if (!se.empty())
            {
                se.erase(p[i]);
            }
            if (!se.empty() && se.find(leader) == se.end())
            {
                leader = -1;
                break;
            }
        }
    }
    if (leader != -1)
    {
        vis[leader] = true;
        ++sum;
    }
}

void Output()
{
    printf("%d\n", sum);
    if (sum == 0) return;

    bool first = true;
    for (int i = 1; i <= n; ++i)
    {
        if (vis[i])
        {
            if (first)
            {
                first = !first;
            }
            else
            {
                printf(" ");
            }
            printf("%d", i);
        }
    }
    puts("");
}

int main()
{
    while (scanf("%d%d", &n, &m) == 2)
    {
        Init();
        Read();
        Solve();
        Output();
    }

    return 0;
}
时间: 2024-11-05 11:36:16

CF - 420B - Online Meeting(思维)的相关文章

CF 452B 4-point polyline(思维)

4-point polyline 大意:给你一个网格,从(0, 0)到(n, m).在网格中选出4个不相同的点,按序相连成3段,求3段想加之和最长的情况是什么,输出这种情况. 思路:当时做的时候各种蛋疼,主要是没想对方向,导致一直WA在第3组.今天看到了一个比较清晰的思路. 首先,确定一个短边,我取了m为较短边. 然后情况主要是分3种: 1.当短边为0的情况: 2.计算dis1 3.计算dis2 4.选出(2)跟(3)中距离之和较大的,输出四个点的顺序. 1 /*****************

CF 729D 模拟,思维

CF 729 D. Sea Battle 题意:n个单位长的海域,有a只船,船长为b.已经开了k枪没有射中,求最少再开几枪可射中一只船. 题解:转变一下思维,求开了k枪后可放入多少只船.要求再开几枪可射中一只船,只要 -a+1即可. #include<bits/stdc++.h> using namespace std; #pragma comment(linker, "/STACK:102400000,102400000") #define FF(i,a,b) for (

CF D. Fair(思维+DFS)

http://codeforces.com/contest/987/problem/D 题目大概: 给出一个n个城镇m条边的图,给出每个城镇拥有的特产(可能多个城镇有相同特产).有k种不同特产. 要求每个城镇需要其他城镇运输特产到自己的城镇,每个城镇必须拥有s种特产,那么在城镇满足s种特产后,需要的最短路径是多长,最短路指的是特产运输过来走过的边的数量. 分析: 一开始以为是道水题,因为我只要对每个点都进行一次DFS,那问题就很简单了,但是...细想下,这其实是不行的,因为会TLE. 那现在我们

CF527D Clique Problem

CF527D Clique Problem 题意简述 数轴上有n 个点,第i 个点的坐标为xi,权值为wi.两个点i,j之间存在一条边当且仅当 abs(xi-xj)>=wi+wj. 你需要求出这张图的最大团的点数.(团就是两两之间有边的顶点集合) solution 简单贪心 化简原式:就是找xi-wi>=xj-wj 那对于一个点i,设li=xi-wi,ri=xi+wi 把每一个点看作[li,ri]间的一条线段,只要表示两点的 线段不重叠,就有一条边,然后就是一道贪心了 CF里面的神奇思维题,难

CF Round433 B. Jury Meeting

题目链接:http://codeforces.com/problemset/problem/853/B 题目大意:自己看吧... 解题思路:刚开始看题解也没看明白,搞了一下午.最后一句话给看到一句话: 排序后前缀最小花费,后缀最小花费,扫一遍就OK了. 具体过程:按照day排序之后,记录前缀最小花费以及对应的最大day,记录后缀最小花费以及对应最小day,然后用双指针对前缀的每一个查找后缀中满足条件的,更新ans即可. 对于前缀,如果j > i, 则 prefix(j) <= prefix(i

CF 750C New Year and Rating(思维题)

题目链接:http://codeforces.com/problemset/problem/750/C 题目: Every Codeforces user has rating, described with one integer, possibly negative or zero. Users are divided into two divisions. The first division is for users with rating 1900 or higher. Those w

cf 1257 E. The Contest(好题)(LIS/思维)

题意: 有三个序列,a.b.c,每次操作可以把一个序列中的一个数移动到另一个序列中, 问,最少操作几次后,可以使得 a 序列里的所有数 小于 b 里面的所有数,b 里面的小于 c 里面的. 数字不重复,总共2e5的数据量. 思路: 做法一:(LIS) 这个做法是网上看到的,确实挺巧妙的,用这个方法,即使以后来个100个序列的,也不用怕了. 分别对a b c 排序,然后合并, 求最大上升子序列,然后上升子序列里的数不动,只移动非序列里的,答案就是 n - len,len最大,答案就最小. 求LIS

CF 19C 思维题STL应用

http://codeforces.com/problemset/problem/19/C Once Bob saw a string. It contained so many different letters, that the letters were marked by numbers, but at the same time each letter could be met in the string at most 10 times. Bob didn't like that s

cf 853 B Jury Meeting [前缀和]

题面: 传送门 思路: 看完题目以后,首先有一个结论:每个人都是先去到首都,等待开会,开会结束以后再一个个走掉 而且这道题只有去首都和离开首都的机场 因此考虑计算去首都的飞机的前缀最小花费,以及离开首都的飞机的最小后缀花费 都计算出来以后,对于每一个开始开会的时间t,用pre[t-1]+suf[t+k]来更新答案即可 Code: 到处都要用long long...... 最后我只好ctrl+R,替换int为longlong了...... 1 #include<iostream> 2 #incl