一道题12

$n \leq 100000$的$a$序列和$m \leq n$的$b$序列,问$a$有多少子串和$b$能匹配。匹配:俩串长度相同,且俩串的数存在一种一一对应的关系使得每一对的和都$>=h$。

把$b$排个序,这样一个$a_i$就能配$b$的一个后缀。设$a_i$能配上后缀$p_i$。一个$b_j$能配上,必须有$>=j$个$p_i$会$<=j$,不然前缀$j$就配不满了。这个用线段树搞搞。

 1 #include<stdio.h>
 2 #include<string.h>
 3 #include<stdlib.h>
 4 //#include<math.h>
 5 //#include<queue>
 6 #include<algorithm>
 7 //#include<iostream>
 8 //#include<assert.h>
 9 using namespace std;
10 
11 int n,m,h;
12 #define maxn 300011
13 int a[maxn],b[maxn],p[maxn];
14 
15 struct SMT
16 {
17     struct Node
18     {
19         int ls,rs;
20         int Max; int add;
21     }a[maxn<<1];
22     int size,n;
23     void clear(int m) {size=0; n=m; a[0].Max=-1e9;}
24     void up(int x) {a[x].Max=max(a[a[x].ls].Max,a[a[x].rs].Max);}
25     void addsingle(int x,int v) {a[x].Max+=v; a[x].add+=v;}
26     void down(int x) {if (a[x].add) {addsingle(a[x].ls,a[x].add); addsingle(a[x].rs,a[x].add); a[x].add=0;}}
27     
28     void build(int &x,int L,int R)
29     {
30         x=++size;
31         if (L==R) {a[x].ls=a[x].rs=0; a[x].Max=L; return;}
32         int mid=(L+R)>>1;
33         build(a[x].ls,L,mid); build(a[x].rs,mid+1,R); up(x);
34     }
35     void build() {int x; build(x,1,n);}
36     int ql,qr,v;
37     void Add(int x,int L,int R)
38     {
39         if (ql<=L && R<=qr) {addsingle(x,v); return;}
40         down(x);
41         int mid=(L+R)>>1;
42         if (ql<=mid) Add(a[x].ls,L,mid);
43         if (qr>mid) Add(a[x].rs,mid+1,R);
44         up(x);
45     }
46     void add(int x,int y,int v) {if (x>y) return; ql=x; qr=y; this->v=v; Add(1,1,n);}
47     int Query(int x,int L,int R)
48     {
49         if (ql<=L && R<=qr) return a[x].Max;
50         down(x);
51         int mid=(L+R)>>1,ans=-1e9;
52         if (ql<=mid) ans=Query(a[x].ls,L,mid);
53         if (qr>mid) ans=max(ans,Query(a[x].rs,mid+1,R));
54         return ans;
55     }
56     int query(int x,int y) {ql=x; qr=y; return Query(1,1,n);}
57 }t;
58 
59 int main()
60 {
61     scanf("%d%d%d",&n,&m,&h);
62     for (int i=1;i<=m;i++) scanf("%d",&b[i]);
63     for (int i=1;i<=n;i++) scanf("%d",&a[i]);
64     sort(b+1,b+1+m);
65     
66     t.clear(m); t.build();
67     int ans=0;
68     for (int i=1;i<=n;i++)
69     {
70         p[i]=lower_bound(b+1,b+1+m,h-a[i])-b;
71         t.add(p[i],m,-1);
72         if (i>m) t.add(p[i-m],m,1);
73         if (t.a[1].Max<=0) ans++;
74     }
75     printf("%d\n",ans);
76     return 0;
77 }
View Code

 

转载于:https://www.cnblogs.com/Blue233333/p/8760652.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一道ACM目的示例: 目描述 给定一个整数数组和一个目标值,找数组中和为目标值的两个数。 你可以假设每个输入只对应一种答案,且同样的元素不能重复使用。 示例 给定 nums = [2, 7, 11, 15], target = 9 因为 nums[0] + nums[1] = 2 + 7 = 9 所以返回 [0, 1] 解思路 这道可以使用哈希表来解决。哈希表中存储每个数的下标,遍历数组时,判断哈希表中是否存在 target-nums[i],如果存在,则说明找到了符合要求的两个数,返回它们的下标即可。 代码实现 C++代码实现: ```cpp #include <iostream> #include <vector> #include <unordered_map> using namespace std; vector<int> twoSum(vector<int>& nums, int target) { unordered_map<int, int> m; for (int i = 0; i < nums.size(); i++) { int complement = target - nums[i]; if (m.count(complement)) { return {m[complement], i}; } m[nums[i]] = i; } return {}; } int main() { vector<int> nums = {2, 7, 11, 15}; int target = 9; vector<int> res = twoSum(nums, target); for (int i = 0; i < res.size(); i++) { cout << res[i] << " "; } return 0; } ``` Python代码实现: ```python def twoSum(nums, target): d = {} for i, n in enumerate(nums): complement = target - n if complement in d: return [d[complement], i] d[n] = i return [] nums = [2, 7, 11, 15] target = 9 print(twoSum(nums, target)) ``` Java代码实现: ```java import java.util.HashMap; public class Solution { public int[] twoSum(int[] nums, int target) { HashMap<Integer, Integer> map = new HashMap<>(); for (int i = 0; i < nums.length; i++) { int complement = target - nums[i]; if (map.containsKey(complement)) { return new int[] {map.get(complement), i}; } map.put(nums[i], i); } return new int[] {}; } } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值