zoukankan      html  css  js  c++  java
  • [LuoguP1360][USACP07MAR]黄金阵容均衡

    [LuoguP1360][USACP07MAR]黄金阵容均衡(Link

    每天会增加一个数(A),将(A)二进制分解为(a[i]),对于每一个(i)都增加(a[i]),如果一段时间之内所有的位数上的数都增加了同一个数,那么成这个天数区间为均衡的。现在要求最长的均衡区间。

    这道题很显然可以使用前缀和。我们统计每一天的前缀和为一个(map)数组(A)。如果区间([L, R])为均衡区间,那么(A[R] - A[L - 1])就一定满足每一个二进制分解的位数都相等。那么我们不妨设一个起始点数组,一个结束点数组。也就是(L[i])(R[i]),那么肯定有(R[i] - L[i] = 0)。也就是(R[1] - L[1] = R[2] - L[1] =..= R[N] - L[N]) 。那么我们进而可以知道(R[i] - R[j] = L[i] - L[j])

    进而我们看到只要每一次计算前缀和后减去第一位的值相等,那么就是一个均衡区间。于是我就(yy)出一种类似于哈希的做法。首先定义每天的状态以及每一种状态对应那一天。然后每次读到一个数,判断现在的状态是否在之前出现过,如果出现过,那么就可以(Ans = max(Ans, i - F[A])),其中(i - F[A])就是当前天数减去当前状态(A)对应的之前的天数,然后取个(max)就可以了。

    可以使用(map)记录状态。

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <vector>
    #include <map>
    #include <algorithm>
    using namespace std ;
    typedef long long LL ;
    const int MAXN = 10010 ;
    const int MAXM = 10010 ;
    const int Inf = 0x7fffffff ;
    LL N, M, Ans ;
    
    map <vector <int>, int> F ;
    
    inline LL Read() {
    	LL X = 0, F = 1 ; char ch = getchar() ;
    	while (ch > '9' || ch < '0') F = (ch == '-' ? - 1 : 1), ch = getchar() ;
    	while (ch >= '0' && ch <= '9') X=(X<<1)+(X<<3)+(ch^48), ch = getchar() ;
    	return X * F ;
    }
    
    int main() {
    	freopen("in.in", "r", stdin) ;
    	N = Read(), M = Read() ; 
    	vector <int> A(M);
    	for (int i = 1 ; i <= N ; i ++) {
    		LL X = Read() ;
    		for (int j = 0 ; j <  M ; j ++)
    			A[j] += (X & (1 << j)) ? 1 : 0 ;
    		if (X & 1) for (int j = 0 ; j <  M ; j ++) A[j] -- ;
    		if (F.count(A)) Ans = max(Ans, LL(i) - F[A]) ;
    		else F[A] = i ;
    	}	printf("%lld", Ans) ; return 0 ;
    }
    
    
  • 相关阅读:
    二叉树
    消息
    线性表 及Java实现 顺序表、链表、栈、队列
    Memcache简介
    redis例子
    redis简介
    Android客户端采用Http 协议Post方式请求与服务端进行数据交互(转)
    jQueryValidate实现重复性验证
    mybatis中${}和#{}的区别
    List转换为数组Array的方法
  • 原文地址:https://www.cnblogs.com/sue_shallow/p/P1360.html
Copyright © 2011-2022 走看看