Codeforces Round #558 (Div. 2)-Cat Party (Hard Edition)-(前缀和 + 模拟)

http://codeforces.com/problemset/problem/1163/B2

题意:有n天,每天有一个颜色,截取前x天,随便抽掉一天,使剩下的各个颜色出现的次数相等。

解题,也可以解决B1:

有三种情况:

1.一种颜色出项一次,其他相等,抽掉出现1次颜色的那一天,例如13天分别是

6 222 333 444 555

2.只有两种颜色次数,次数相差1,并且最大出现次数的颜色只有1次,例如13天分别是

777 333 222 8888

3.所有颜色都只出现过1次,例如

1 2 3 4 5 6 7 8 9

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

int a[200086];///每一天的颜色
int color[200086];///下标颜色出现的次数
int n;

int main()///cf558div2B
{
    while(scanf("%d",&n)!=EOF)
    {
        memset(a,0,sizeof(a));
        memset(color,0,sizeof(color));
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&a[i]);
        }
        int sum=0;/// 一共出现几种颜色
        int maxx=-1,ans=0;///最大次数 答案
        int one=0; ///特判颜色次数为1的颜色数量
        set<int>se;///判断当前颜色是否出现过
        map<int,int>mp;///快速找到最大次数的颜色数
        for(int i=1;i<=n;i++)
        {
            if( !se.count(a[i]) )
            {
                sum++;
                se.insert(a[i]);
            }
            color[ a[i] ]++;
            mp[ color[ a[i] ] ]++;///每一次都累加,最后只需要用到maxx和maxx-1

            if( color[ a[i] ]==1 )
                one++;
            else if( color[ a[i] ]==2 )///颜色出现的次数超过1自然会先变成2,并且回不来了
                one--;

            if( color[ a[i] ] > maxx )
                maxx=color[  a[i] ];

            if( mp[maxx]==1 && mp[maxx-1]==sum )
                ans=i;
            if( mp[maxx]==sum-1 && one==1 )
                ans=i;
            if(maxx==1 && mp[maxx]==sum)
                ans=i;
        }
        printf("%d\n",ans);
    }
    return 0;
}

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

时间: 2024-10-09 04:11:52

Codeforces Round #558 (Div. 2)-Cat Party (Hard Edition)-(前缀和 + 模拟)的相关文章

Codeforces Round #257 (Div. 2) E题:Jzzhu and Apples 模拟

E. Jzzhu and Apples time limit per test 1 second memory limit per test 256 megabytes input standard input output standard output Jzzhu has picked n apples from his big apple tree. All the apples are numbered from 1 to n. Now he wants to sell them to

CodeForces Round #558 Div.2

A. Eating Soup #include <bits/stdc++.h> using namespace std; int N, M; int main() { scanf("%d%d", &N, &M); int ans; if(N == M) ans = 0; else if(M == 0 || M == 1 || M == N - 1) ans = 1; else { if(M <= N / 2) ans = M; else ans = N

Codeforces Round 558(Div 2)题解

这场比赛没有打,后来和同学们一起开了场镜像打…… B是SB题结果WA了5发…… C是SB题结果差5min调出……虽然中间有个老师讲题吃掉了1h D是比较神仙的题(2200),但是做出来了?算是比较超常发挥了.(平常能做出的题中最难的就是2200了) E是2800,F是2900,zblzbl…… 这次发挥还是不错的,写一篇题解吧. A 首先发现在一个圆上删掉 $m$ 个点,段数的上界为 $m$.($0$ 除外,所以要特判 $0$) 然后剩下了 $n-m$ 个点.答案就是 $\min(m,n-m)$

Codeforces Round #271 (Div. 2)D(递推,前缀和)

很简单的递推题.d[n]=d[n-1]+d[n-k] 注意每次输入a和b时,如果每次都累加,就做了很多重复性工作,会超时. 所以用预处理前缀和来解决重复累加问题. 最后一个细节坑了我多次: printf("%I64d\n",(s[b]-s[a-1]+mod)%mod); 这句话中加mod万万不能少,因为理论上s[b]-s[a-1]肯定大于0,但是由于两个都是模1000000007以后的结果,那么就不一定了,当s[b]-s[a-1]<0时结果是负的,不是题意中应该输出的结果,所以一

Codeforces Round #428 (Div. 2)

Codeforces Round #428 (Div. 2) A    看懂题目意思就知道做了 #include<bits/stdc++.h> using namespace std; #pragma comment(linker, "/STACK:102400000,102400000") #define rep(i,a,b) for (int i=a; i<=b; ++i) #define per(i,b,a) for (int i=b; i>=a; --i

Codeforces Round #424 (Div. 2) D. Office Keys(dp)

题目链接:Codeforces Round #424 (Div. 2) D. Office Keys 题意: 在一条轴上有n个人,和m个钥匙,门在s位置. 现在每个人走单位距离需要单位时间. 每个钥匙只能被一个人拿. 求全部的人拿到钥匙并且走到门的最短时间. 题解: 显然没有交叉的情况,因为如果交叉的话可能不是最优解. 然后考虑dp[i][j]表示第i个人拿了第j把钥匙,然后 dp[i][j]=max(val(i,j),min(dp[i-1][i-1~j]))   val(i,j)表示第i个人拿

Codeforces Round #424 (Div. 2) C. Jury Marks(乱搞)

题目链接:Codeforces Round #424 (Div. 2) C. Jury Marks 题意: 给你一个有n个数序列,现在让你确定一个x,使得x通过挨着加这个序列的每一个数能出现所有给出的k个数. 问合法的x有多少个.题目保证这k个数完全不同. 题解: 显然,要将这n个数求一下前缀和,并且排一下序,这样,能出现的数就可以表示为x+a,x+b,x+c了. 这里 x+a,x+b,x+c是递增的.这里我把这个序列叫做A序列 然后对于给出的k个数,我们也排一下序,这里我把它叫做B序列,如果我

[Codeforces] Round #352 (Div. 2)

人生不止眼前的狗血,还有远方的狗带 A题B题一如既往的丝帛题 A题题意:询问按照12345678910111213...的顺序排列下去第n(n<=10^3)个数是多少 题解:打表,输出 1 #include<bits/stdc++.h> 2 using namespace std; 3 int dig[10],A[1005]; 4 int main(){ 5 int aa=0; 6 for(int i=1;;i++){ 7 int x=i,dd=0; 8 while(x)dig[++dd

Codeforces Round #273 (Div. 2)

Codeforces Round #273 (Div. 2) 题目链接 A:签到,仅仅要推断总和是不是5的倍数就可以,注意推断0的情况 B:最大值的情况是每一个集合先放1个,剩下都丢到一个集合去,最小值是尽量平均去分 C:假如3种球从小到大是a, b, c,那么假设(a + b) 2 <= c这个比較明显答案就是a + b了.由于c肯定要剩余了,假设(a + b)2 > c的话,就肯定能构造出最优的(a + b + c) / 3,由于肯定能够先拿a和b去消除c,而且控制a和b成2倍关系或者消除