zoukankan      html  css  js  c++  java
  • FZU1465

    题目链接:传送门

    题目大意:给你n个整数(可正可负),求有多少个连续的子序列的和==m(时限1S)

    题目思路:前缀和+手写hash(map效率太慢,会超时)

                具体做法是用一个数组sum,数组的第i位保存前1~i个数的和,那么从第x个元素到到第y个元素的和就可以表示为sum[y]-sum[x]

                现在我们要求有多少个连续子序列的和==m,也就是找出有多少个sum[y]-sum[x]==m。

         如果给你的数都是正整数就好办了,不难想到可以用尺取法(双指针扫描),但是难点在于有负数,也就是sum数组的值很杂乱。

                但其实,我们观察一下式子    sum[y]-sum[x]==m,如果把它转换一下   sum[y]-m=sum[x]。那么我们对于sum[i],只需要找到

                在i之前出现了多少sum[i]-m,答案就加上sum[i]-m的个数,所以我们只需从头扫一遍即可。复杂度O(n),但是map效率太慢,所以还需

                手写hash

    MAP超时代码

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <algorithm>
     4 #include <queue>
     5 #include <vector>
     6 #include <string>
     7 #include <stack>
     8 #include <cmath>
     9 #include <cstdlib>
    10 #include <iostream>
    11 #include <map>
    12 using namespace std;
    13 const int INF = 0x3f3f3f3f;
    14 typedef long long ll;
    15 const int mod = 1234577;
    16 const int N = 1e6 + 1000;
    17 map<ll, int> mp;
    18 
    19 ll sum[N];
    20 int main() {
    21     int n, m, v;
    22     int group; scanf("%d", &group);
    23     while(group--) {
    24         scanf("%d%d", &n, &m);
    25         sum[0] = 0;
    26         for(int i = 1; i <= n; ++i) {
    27             scanf("%d", &v);
    28             sum[i] = sum[i - 1] + v;
    29         }
    30         int ans = 0;
    31         mp.clear(); mp[0] = 1;
    32         for(int i = 1; i <= n; ++i) {
    33             ll s = sum[i] - m;
    34             int num = mp[s];
    35             ans += num;
    36 
    37             mp[sum[i]]++;
    38         }
    39         printf("%d
    ", ans);
    40     }
    41     return 0;
    42 }

    AC代码

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstdlib>
     4 #include <cmath>
     5 #include <algorithm>
     6 #include <cstring>
     7 #define mst(x,y) memset(x,y,sizeof(x))
     8 using namespace std;
     9 const long long MOD=(1ll<<50);
    10 const long long MMM=1234567;
    11 const int N=1000005;
    12 
    13 int n,m;
    14 long long key[N],sum[N];
    15 int head[MMM],cnt[N],next[N],hcnt;
    16 struct Myhas{
    17     void init(){
    18         mst(head,-1);
    19         mst(cnt,0);
    20         hcnt=0;
    21     }
    22     void ins(long long x){
    23         int h=x%MMM;
    24         key[hcnt]=x;
    25         cnt[hcnt]=1;
    26         next[hcnt]=head[h];
    27         head[h]=hcnt++;
    28     }
    29     void add(long long x){
    30         int h=x%MMM;
    31         for(int i=head[h];~i;i=next[i]){
    32             if(key[i]==x){++cnt[i];return;}
    33         }
    34     }
    35     int query(long long x){
    36         int h=x%MMM;
    37         for(int i=head[h];~i;i=next[i]){
    38             if(key[i]==x) return cnt[i];
    39         }
    40         return -1;
    41     }
    42 }has;
    43 int main(){
    44     int i,j,group,x,ans;
    45     scanf("%d",&group);
    46     while(group--){
    47         scanf("%d%d",&n,&m);
    48         for(i=1;i<=n;++i){
    49             scanf("%d",&x);
    50             sum[i]=sum[i-1]+x;
    51         }
    52         ans=0;
    53         has.init();
    54         has.ins(MOD);
    55         for(i=1;i<=n;++i){
    56             long long xx=sum[i]-m+MOD;
    57             int num=has.query(xx);
    58             if(num!=-1)ans+=num;
    59             xx=(sum[i]+MOD);
    60             if(has.query(xx)!=-1)has.add(xx);
    61             else has.ins(xx);
    62         }
    63         printf("%d
    ",ans);
    64     }
    65     return 0;
    66 }

               

  • 相关阅读:
    关于源码编译每次提示有错误 要make update-api
    如何在Android中添加系统服务
    git查看每个版本间的差异
    achartengine画出动态折线图
    java中基本数据类型和C语言中基本数据类型转换
    获取图片的真实宽高
    hdu-2066-一个人的旅行
    Linux内核模块编程与内核模块LICENSE -《具体解释(第3版)》预读
    Android平台Camera实时滤镜实现方法探讨(十一)--实时美颜滤镜
    ios9定位服务的app进入后台三分钟收不到经纬度,应用被挂起问题及解决方式
  • 原文地址:https://www.cnblogs.com/Kurokey/p/5542491.html
Copyright © 2011-2022 走看看