题目链接:传送门

题目大意:给你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超时代码

 #include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <vector>
#include <string>
#include <stack>
#include <cmath>
#include <cstdlib>
#include <iostream>
#include <map>
using namespace std;
const int INF = 0x3f3f3f3f;
typedef long long ll;
const int mod = ;
const int N = 1e6 + ;
map<ll, int> mp; ll sum[N];
int main() {
int n, m, v;
int group; scanf("%d", &group);
while(group--) {
scanf("%d%d", &n, &m);
sum[] = ;
for(int i = ; i <= n; ++i) {
scanf("%d", &v);
sum[i] = sum[i - ] + v;
}
int ans = ;
mp.clear(); mp[] = ;
for(int i = ; i <= n; ++i) {
ll s = sum[i] - m;
int num = mp[s];
ans += num; mp[sum[i]]++;
}
printf("%d\n", ans);
}
return ;
}

AC代码

 #include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#include <cstring>
#define mst(x,y) memset(x,y,sizeof(x))
using namespace std;
const long long MOD=(1ll<<);
const long long MMM=;
const int N=; int n,m;
long long key[N],sum[N];
int head[MMM],cnt[N],next[N],hcnt;
struct Myhas{
void init(){
mst(head,-);
mst(cnt,);
hcnt=;
}
void ins(long long x){
int h=x%MMM;
key[hcnt]=x;
cnt[hcnt]=;
next[hcnt]=head[h];
head[h]=hcnt++;
}
void add(long long x){
int h=x%MMM;
for(int i=head[h];~i;i=next[i]){
if(key[i]==x){++cnt[i];return;}
}
}
int query(long long x){
int h=x%MMM;
for(int i=head[h];~i;i=next[i]){
if(key[i]==x) return cnt[i];
}
return -;
}
}has;
int main(){
int i,j,group,x,ans;
scanf("%d",&group);
while(group--){
scanf("%d%d",&n,&m);
for(i=;i<=n;++i){
scanf("%d",&x);
sum[i]=sum[i-]+x;
}
ans=;
has.init();
has.ins(MOD);
for(i=;i<=n;++i){
long long xx=sum[i]-m+MOD;
int num=has.query(xx);
if(num!=-)ans+=num;
xx=(sum[i]+MOD);
if(has.query(xx)!=-)has.add(xx);
else has.ins(xx);
}
printf("%d\n",ans);
}
return ;
}

FZU1465的更多相关文章

随机推荐

  1. sql server 数据加密

    select EncryptByPassPhrase('hksjlm',qlrmc)jmsj,* into jmqlr from qlr where qlbh in('5201411120005',' ...

  2. 修改配置nginx,限制无良爬虫频率

    配置如下: #全局配置 limit_req_zone $anti_spider zone=anti_spider:10m rate=15r/m; #某个server中 limit_req zone=a ...

  3. oracle经验小节2

    1,instr 函数 在Oracle/PLSQL中,instr函数返回要截取的字符串在源字符串中的位置. 语法如下: instr( string1, string2 [, start_position ...

  4. C#实现播放声音的方法

    文章来自学IT网:http://www.xueit.com/html/2009-09/21_4598_00.html 在这里介绍使用C#实现播放声音的几种方法,都是利用组件等方法来实现的,有兴趣的话可 ...

  5. php5 升级 php7 版本遇到的问题处理方法总结

    为了能够更好的提升系统的安全性,把原来的进销存系统源码升级,遇到了一些问题在这儿总结一下: 1.mysql引擎在php7中不在支持会导致以下错误 Uncaught Error: Call to a m ...

  6. 接收广播BroadcastReceiver

    Broadcast Receiver用于接收并处理广播通知(broadcast announcements).多数的广播是系统发起的,如地域变换.电量不足.来电来信等.程序也可以播放一个广播.程序可以 ...

  7. php对xml文件的增删改查

    源文件<?xml version="1.0" encoding="utf-8"?><root>  <endTime>2016 ...

  8. 实验c语言不同类型的指针互用(不推荐只是学习用)

    #include <stdio.h> int main(int argc, char *argv[]) { printf("Hello, world\n"); ]; i ...

  9. Java并发编程(四):线程安全性

    一.定义 当多个线程访问某个类时,不管运行时环境采用何种调度方式或者这些进程将如何交替执行,并且在主调代码中不需要额外的同步或协同,这个类都能表现出正确的行为,那么就称这个类是线程安全的. 二.线程安 ...

  10. hdu 4771 Stealing Harry Potter's Precious (2013亚洲区杭州现场赛)(搜索 bfs + dfs) 带权值的路径

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4771 题目意思:'@'  表示的是起点,'#' 表示的是障碍物不能通过,'.'  表示的是路能通过的: ...