/*
n个数,求最长的连续一段,使得这一段数字,二进制中每一位拥有1的那些数字的个数相等
n<=10^5,位数k<=30
如
7 2 1 4 这里每一位1都有2个数字拥有
容易想到先预处理出sum[n,k]表示前面n个数字中在第k位是1的个数
这k个数字sum[n,k]的样子就是曲线形的,如sum[i,k]为
_ /\
/ \/ \_/\
为了使得sum[i,k] - sum[j,k]对所有k都是同一个数
则sum[j,k]的样子也必须是这样的,这样sum[i,k] - sum[j,k]才是一个同一个数(类似拼接时图形需吻合)
好了,所以我们需要保存这个图形,可以通过保存a[i,k] = sum[i,k] - sum[i,0]即可(即保存相对值) -----OMG
我一开始用map<vector<int>, int>, vector<int>是保存图形,int是保存第一次出现的地方
在for到i时,计算出图形,在map中找有没出现过,有的话就更新答案为i-mp[vt]
vector是有重载比较运算符的,所以不用写其他
但是超时了,我在本机测貌似不会超时 --||
看了解题报告,方法一样,但是不是用map,是最后sort一次的
对哦,我想起之前也有一道题,又不需要每个i都输出结果,不用map,直接最后sort一次更好
用map会慢一点
但这样还超时,原来是vector的比较比较慢
自己写了个struct Node {int vt[30];}; 再重载比较过了
sort时,可以对下标排序,减少了大数据移动
这题官方有另外解法,就是对数组vt[30] hash
好的hash函数会快很多吧
hsize=997001;
for(p=0,i=0;i<k;i++)
p=((p<<2)+(v[i]>>4))^(v[i]<<10);
p=p%hsize;
if(p<0) p+=hsize;
*/
#include<iostream>
#include<cstring>
#include<map>
#include<algorithm>
#include<stack>
#include<queue>
#include<cstring>
#include<cmath>
#include<string>
#include<cstdlib>
#include<vector>
#include<cstdio>
#include<set>
#include<list>
#include<numeric>
#include<cassert>
#include<sstream>
#include<ctime>
#include<bitset>
#include<functional>
using namespace std;
const int MAXN = 100100;
int n, k;
struct Node
{
int vt[30];
void clear()
{
memset(vt, 0, sizeof vt);
}
};
bool operator < (const Node &A, const Node &B) //直接用vector的比较会慢 可能数据太大吧
{
for (int i = 0; i < k - 1; i++) {
if (A.vt[i] != B.vt[i]) {
return A.vt[i] < B.vt[i];
}
}
return false;
}
pair<Node, int> all[MAXN];
inline bool cmp(const int &a, const int &b)
{
return all[a] < all[b];
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("in","r",stdin);
#endif
for (; ~scanf("%d%d", &n, &k); ) {
// long long start = clock();
vector<int> vt(k-1), pos(n+1);
all[0].first.clear();//don't forget to push k-1 zeros
all[0].second = 0;
pos[0] = 0;
vector<int> sum(k);
for (int i = 1, x; i <= n; i++) {
scanf("%d", &x);
for (int j = 0; j < k; j++) {
sum[j] += (x>>j) & 1;
if (j > 0) {
all[i].first.vt[j-1] = sum[j] - sum[j-1];
}
}
all[i].second = i;
pos[i] = i;
}
sort(pos.begin(), pos.end(), cmp);
int ans = 0;
for (int i = 1, last = 0; i <= n+1; i++) {
if (i == n+1 || all[pos[i-1]].first < all[pos[i]].first) {
ans = max(ans, all[pos[i-1]].second - all[pos[last]].second);
last = i;
}
}
printf("%d\n", ans);
// cout<<"time "<<clock() - start<<endl;
}
return 0;
}
|
|
常用链接
随笔分类
Links
搜索
最新评论
|
|