ACM-ICPC 2017 西安赛区现场赛 K. LOVER II && LibreOJ#6062. 「2017 山东一轮集训 Day2」Pair(线段树)

题目链接:西安:https://nanti.jisuanke.com/t/20759   (计蒜客的数据应该有误,题目和 LOJ 的大同小异,题解以 LOJ 为准)

        LOJ:https://loj.ac/problem/6062

题意:给出一个长度为n的数列a_i和一个长度为m的数列b_i求a_i有多少个长度为m的连续子数列能与b_i匹配。 两个数列可以匹配,当且仅当存在一种方案,使两个数列中的数可以两两配对,两个数可以配对当且仅当它们的和不小于h。

题解:先对 b 数组进行排序,建一颗线段树,将 b 数组中位置为 i 的数初始化为 -i ,那么当 [1,m] 中最小值大于等于 0 时即可匹配。枚举 a 的左端点,同时记录满足条件的最小右端点,当右端点 - 左端点 = m 时子区间满足条件 ans++。(西安现场赛的题则记录左端点可以匹配的最小右端点即可)

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 #define ll long long
 4 #define ull unsigned long long
 5 #define mst(a,b) memset((a),(b),sizeof(a))
 6 #define mp(a,b) make_pair(a,b)
 7 #define pi acos(-1)
 8 #define pii pair<int,int>
 9 #define pb push_back
10 const int INF = 0x3f3f3f3f;
11 const double eps = 1e-6;
12 const int MAXN = 15e4 + 10;
13 const int MAXM = 2e6 + 10;
14 
15 int a[MAXN], b[MAXN];;
16 int st[MAXN << 2], lazy[MAXN << 2];
17 
18 void pushup(int rt) {
19     st[rt] = min(st[rt << 1],st[rt << 1 | 1]);
20 }
21 
22 void build(int rt,int l,int r) {
23     if(l == r) {
24         st[rt] = -l;
25         return ;
26     }
27     int mid = (l + r) >> 1;
28     build(rt << 1,l,mid);
29     build(rt << 1 | 1,mid + 1,r);
30     pushup(rt);
31 }
32 
33 void pushdown(int rt) {
34     if(lazy[rt]) {
35         lazy[rt<<1] += lazy[rt], lazy[rt<<1|1] += lazy[rt];
36         st[rt<<1] += lazy[rt], st[rt<<1|1] += lazy[rt];
37         lazy[rt] = 0;
38     }
39 }
40 
41 void update(int rt,int l,int r,int ql,int qr,int val) {
42     if(qr < ql) return ;
43     if(ql <= l && qr >= r) {
44         st[rt] += val;
45         lazy[rt] += val;
46         return ;
47     }
48     pushdown(rt);
49     int mid = (l + r) >> 1;
50     if(ql <= mid) update(rt<<1,l,mid,ql,qr,val);
51     if(qr > mid) update(rt<<1|1,mid+1,r,ql,qr,val);
52     pushup(rt);
53 }
54 
55 int query(int rt,int l,int r,int ql,int qr) {
56     if(ql <= l && qr >= r) return st[rt];
57     int mid = (l + r) >> 1;
58     int ans = 1e9;
59     if(ql <= mid) ans = min(ans,query(rt<<1,l,mid,ql,qr));
60     if(qr > mid) ans = min(ans,query(rt<<1|1,mid+1,r,ql,qr));
61     return ans;
62 }
63 
64 int main() {
65 #ifdef local
66     freopen("data.txt", "r", stdin);
67 //    freopen("data.txt", "w", stdout);
68 #endif
69     int n,m,h;
70     scanf("%d%d%d",&n,&m,&h);
71     for(int i = 1; i <= m; i++) scanf("%d",&b[i]);
72     for(int i = 1; i <= n; i++) scanf("%d",&a[i]);
73     sort(b + 1, b + 1 + m);
74     build(1,1,m);
75     int now = 0, ans = 0;
76     for(int i = 1; i <= n; i++) {
77         while(query(1,1,m,1,m) < 0 && now < n) {
78             int val = a[++now];
79             int pos = lower_bound(b + 1, b + 1 + m, h - val) - b;
80             update(1,1,m,pos,m,1);
81         }
82         if(query(1,1,m,1,m) >= 0 && now == i + m - 1) ans++;
83         int pos = lower_bound(b + 1, b + 1 + m, h - a[i]) - b;
84         update(1,1,m,pos,m,-1);
85     }
86     printf("%d
",ans);
87     return 0;
88 }
原文地址:https://www.cnblogs.com/scaulok/p/9698776.html