HDU 5358 First One(枚举)

这道题如果按照表达式一个个来算肯定超时,下午时候想了一个O(nlogn*logn)的算法,但是t了,因为这道题卡的非常紧几百个样例,必须nlogn的算法才可以ac

回到这道题,考虑log(sum(i,j))+1的特点,可以发现它的值域范围非常小,在1-34之间,那么我们可以考虑枚举log(sum(i,j)+1的值,记为k,然后统计(i+j)的和即可。

对于每一个k,找到所有满足2^(k-1)<=sum(i,j)<=2^k-1的(i+j),

那么我们考虑每个前缀i,找到这个前缀满足2^(k-1)<=sum(i,j)<=2^k-1的区间[l,r],即对于这个区间的每个元素s(i,j),都满足上式(l<=j<=r)。

这一步枚举有一个小技巧,当我们找到前缀i的区间[l,r]之后,那么前缀i+1满足上式的区间一定不可能在前缀i的[l, r]之前。

那么我们用两个指针维护这个区间即可,那么时间复杂度就降为了O(n*logn).

ps:下午写的n*logn*logn的代码在我电脑上跑了22000ms,ac代码在我电脑上跑了5500ms,ac代码在oj上跑了1600ms。

#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<vector>
#include<map>
#include<queue>
#include<stack>
#include<string>
#include<ctime>
#include<map>
#include<set>
#define eps 1e-6
#define LL long long
#define pii (pair<int, int>)
//#pragma comment(linker, "/STACK:1024000000,1024000000")
using namespace std;  

const int maxn = 100000 + 500;
//const int INF = 0x3f3f3f3f;
LL a[maxn], s[maxn];
int n;

int main() {
	clock_t start = clock();
//	freopen("input.txt", "r", stdin);
	int T; cin >> T;
	while(T--) {
		scanf("%d", &n);
		LL ans = 0;
		for(int i = 1; i <= n; i++) {
			scanf("%I64d", &a[i]);
			s[i] = s[i-1] + a[i];
		}
		for(int k = 1; k <= 34; k++) {
			int l = 1, r = 0;
			LL liml = k==1 ? 0 : (1LL<<(k-1)), limr = (1LL<<k)-1;
			for(int i = 1; i <= n; i++) {
				l = max(i, l);
				while(l<=n && s[l]-s[i-1]<liml) l++;
				r = max(l-1, r);
				while(r+1<=n && s[r+1]-s[i-1]>=liml && s[r+1]-s[i-1]<=limr) r++;
				if(l>r) continue;
			//	if(k==2) cout << l << " " << r << " " << i << endl;
				ans += (LL)(i+l+i+r)*(r-l+1)/2*k;
			}
		//	if(k < 5) cout << ans << endl;
		}
		cout << ans << endl;
	}
	clock_t end = clock();
//	cout << end-start << endl;
	return 0;
}



版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-10 09:40:52

HDU 5358 First One(枚举)的相关文章

HDU 5358 First One(枚举+尺举法)

题目链接:传送门 题意:设f(i,j)表示区间[i,j]内元素的和 ,定义 SUM(i,j) = [log2(f(i,j))+1]*(i+j) 求 sigma(sum (i,j)) ( 1<=i<=n,i<=j<=n ) 分析: log2(f(i,j))表示f(i,j)转换为2进制的长度,然后我们经过分析log2(f(i,j))+1的值域 为[1,34]然后我们枚举log2(f(i,j))+1的值,例如我们枚举其值为k,对于一个k我们找到所有满足 条件的区间(i,j),这个条件的代

Hdu 5358 First One (尺取法+枚举)

题目链接: Hdu 5358 First One 题目描述: 数组a有n个元素,S[i,j]定义为a[i]+a[i+1]+.....+a[j],问:这个死东西等于多少? 解题思路: 二分肯定超,这个题目的时间卡的炒鸡严格,只有n*log(n)的复杂度才能过,n*log(n)^2都不可以的. 只需要枚举K,并且枚举区间左端i值,计算K的贡献值,然后遍历时候计算一下常数相加即可. 1 #include <cstdio> 2 #include <cstring> 3 #include &

HDU 5358 多校第6场 First One

First One Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others) Total Submission(s): 672    Accepted Submission(s): 193 Problem Description soda has an integer array . Let  be the sum of . Now soda wants to know the va

HDU 3709 Balanced Number 枚举+数位DP

枚举支点之后数位DP,注意姿势 #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #include <climits> #include <string> #include <iostream> #include <map> #include <cstdlib> #include <list&g

HDU 5358(2015多校联合训练赛1006) First One (区间合并+常数优化)

HDU 5358 题意: 求∑?i=1?n??∑?j=i?n??(?log?2??S(i,j)?+1)?(i+j). 思路: S(i,j) < 10^10 < 2^34,所以log2(S)+1的值只可能在1~35之间.由于log变化缓慢的函数特性,我们可以S(i,n)分作多个相同log值的区间来计算,用pos[i][j]预处理记录每个以i为起点,log(s)值为j的区间的右边界,即可优化至nlogn的复杂度. 主要是写起来比较难一些,一些细节比较纠结,一定思路理清后再写. ps.此题卡常数毫无

hdu 5358 First One 2015多校联合训练赛#6 枚举

First One Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others) Total Submission(s): 142    Accepted Submission(s): 37 Problem Description soda has an integer array a1,a2,-,an. Let S(i,j) be the sum of ai,ai+1,-,aj. No

HDU 5358 枚举+尺选

soda has an integer array a1,a2,…,ana1,a2,…,an. Let S(i,j)S(i,j) be the sum of ai,ai+1,…,ajai,ai+1,…,aj. Now soda wants to know the value below: ∑i=1n∑j=in(⌊log2S(i,j)⌋+1)×(i+j) Note: In this problem, you can consider log20 as 0. InputThere are multi

hdu 5358 First One (尺取法)

题目:http://acm.hdu.edu.cn/showproblem.php?pid=5358 题意: 分析:首先要知道[log2(x)]+1代表x的位数,而且根据题意不会超过35,那么枚举位数i:1~35.对于每一位i找到区间[x,y],使得S(x,y)的二进制表示的位数等于i,此时的贡献为i*(x+y).那么对于每一个i,怎么找出所有符合条件的区间[x,y]?1~n枚举起点x,那么y会在一段范围[l,r]内满足条件.下次x变成x+1,即起点x向右移位,那么现在要找的y的区间为[l',r'

hdu 5358 First One 数学

链接 :http://acm.hdu.edu.cn/showproblem.php?pid=5358 First One Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others) Total Submission(s): 871    Accepted Submission(s): 271 Problem Description soda has an integer array a