把博客园图标替换成自己的图标
把博客园图标替换成自己的图标end

【STL】均衡(洛谷P1360)

题目描述

小 F 在许多方面都有着很强的能力。她总共有 m 种能力,这些能力编号为 1,...,m

小 F 每天都会有一些能力得到一次提升。每天的能力提升可以用一个数字表示, 称之为能力提升数字,该数字的二进制位从低到高(即从右到左)第 i 位是 1 表示编号为 i的能力得到了一次提升。比如能力提升数字 13,转化为二进制为 1101,表示编号为 1,3,4 的能力(注意不是 1, 2, 4)分别得到了一次提升。

小 F 把每天的能力提升数字的记了下来,如果在连续的一段时间内,她的每项能力都提升了相同的次数,她就会称这段时间为一段均衡时期,比如在第 36 天,她的每种能力都提升了 2 次,那么这就是一段长度为 4 的均衡时期。

于是问题来了,给出小 F 在 n 天内的能力提升数字,请求出均衡时期的最大长度。

输入格式

第一行有两个整数 n,m,表示有 n 天,m 种能力。

接下来有 n 行,每行有一个整数,分别表示第 1,...,n 天的能力提升数字。 能力提升数字转化为二进制后,从低到高的每一位表示对应的能力是否在当天 得到了一次提升。

输出格式

输出只有一个整数,表示长度最大的均衡时期的长度。

数据范围

对于 50% 的数据,1n1000。

对于 100% 的数据,1n10^5,1m30。

Solution

非常有意思的题目,初看没有思路,后来想到了前缀和,然后暴力枚举端点拿了50%的分数,然后我们可以发现,举个例子,假设前j个数字最后的状态为2 9 10 8,前i个状态为0 7 8 6,则i,j段是平衡的,我们可以发现我们能用一种方式来表达他们,即固定某一位为0,此时只要判断两个端点相同即可求出一段平衡,使用vector存状态,是用map存对应状态第一次出现的位置,更新答案就判断这一状态是否出现过,出现过就拿当前位置减去最早出现的位置。

Code

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define max(a,b) a>b?a:b
 4 map<vector<int>,int> Ma;
 5 int main()
 6 {
 7     int N,M,Ans=-1;
 8     scanf("%d%d",&N,&M);
 9     vector<int> Q;
10     Q.resize(M);
11     Ma[Q]=1;
12     for(int __=1;__<=N;__++){
13         int X,Key=1;
14         scanf("%d",&X);
15         for(int i=0;i<M;i++){
16             if(X&(1<<i)) Q[i]++;
17             if(!Q[i]) Key=0;
18         }
19         for(int i=0;i<M;i++)
20             Q[i]-=Key;
21         if(Ma[Q]) Ans=max(Ans,__-Ma[Q]+1);
22         else Ma[Q]=__+1;
23         
24     }
25     if(Ans<0)
26     cout<<Ans;
27     else cout<<0;
28     return 0;
29 }

 

posted @ 2020-08-17 21:47  fluoce  阅读(148)  评论(0编辑  收藏  举报

Contact with me