zoukankan      html  css  js  c++  java
  • HDU 5358 First One 数学+尺取法

    多校的题,摆明了数学题,但是没想出来,蠢爆了,之前算了半天的s[i][j]的和,其实是积。其实比赛的时候我连log(s[i][j])+1是s[i][j]的位数都没看出来,说出来都丢人。

    知道了这个之后,就枚举二进制数的每一位,因为元素都是非负数,所以sum数组是非降的,这里用到了尺取法,之前也是听说过,应该是做过吧,不太记得了。

    因为[2k-1,2k)的位数是k,枚举时,固定左端点,在sum数组找到最小的大于等于2k-1,最大的小于2k的点,这中间的点和左端点的s[i][j]就对于当前的k满足条件了,就把这些答案加到答案中,复杂度就是O(nlogn)

    其实我的代码并没有AC,一直是超时,但是我做了一些极限的数据在本机上也是秒出,当然是我程序的原因,不过我现在还不知道怎么回事,花了这么多时间了,就这样吧。

    哈哈原来是编译器的问题,之前交的C++,刚交了发G++就A了,

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <fstream>
     4 #include <algorithm>
     5 #include <cmath>
     6 #include <deque>
     7 #include <vector>
     8 #include <queue>
     9 #include <string>
    10 #include <cstring>
    11 #include <map>
    12 #include <stack>
    13 #include <set>
    14 #define LL long long
    15 #define INF 0x3f3f3f3f
    16 #define OPEN_FILE
    17 #define MAXN 100005
    18 using namespace std;
    19 LL sum[MAXN], p[MAXN];
    20 LL ans;
    21 int main()
    22 {
    23 #ifdef OPEN_FILE
    24     freopen("in.txt", "r", stdin);
    25     //freopen("out.txt", "w", stdout);
    26 #endif // OPEN_FILE
    27     int T;
    28     scanf("%d", &T);
    29     p[0] = 0;
    30     p[1] = 2;
    31     for(int i = 2; i <= 34; i++){
    32         p[i] = p[i - 1] * 2;
    33     }
    34     for(int cas = 1; cas <= T; cas++){
    35         int n;
    36         scanf("%d", &n);
    37         memset(sum, 0, sizeof(sum));
    38         int x;
    39         for(int i = 1; i <= n; i++){
    40             scanf("%d", &x);
    41             sum[i] = sum[i - 1] + x;
    42         }
    43         ans = 0;
    44         for(int i = 0; i <= 33; i++){
    45             LL left = 1, right = 1;
    46             for(int j = 1; j <= n; j++){
    47                 left = max((LL)j, left);
    48                 right = max((LL)j, right);
    49                 while(left <= n && sum[left] - sum[j - 1] < p[i]){
    50                     left++;
    51                 }
    52                 //int right = left;
    53                 while(right <= n && sum[right] - sum[j - 1] < p[i + 1]){
    54                     right++;
    55                 }
    56                 right--;
    57                 if(right > n){
    58                     right = n;
    59                 }
    60                 if(left <= right){
    61                     ans += ((((left + right)*(right - left + 1)) / 2) + (right - left + 1) * j)  * (LL)(i + 1);
    62                 }
    63             }
    64             if(p[i + 1] > sum[n]){
    65                 break;
    66             }
    67         }
    68         printf("%I64d
    ", ans);
    69     }
    70 }
  • 相关阅读:
    自动支持图片webp格式压缩,图片服务器升级webserver
    长江商学院介绍及名人校友名单
    恒大许家印靠斗着地主,当上首富
    用GitLab搭建自己的私有GitHub
    vim快速定位到某一行的几种方法和显示行号,定位匹配字符串,显示当前行信息的命令
    mysql数据库表上百万记录优化思路杂谈
    Java打印输出数组的三种方式:传统的for循环方式,for each循环,利用Arrays类中的toString方法
    个人快速成长之系统方法,最小化成长系统
    程序员应该了解的常见软件开发定律
    用python修改文件内容修改txt内容的3种方法
  • 原文地址:https://www.cnblogs.com/macinchang/p/4712191.html
Copyright © 2011-2022 走看看