题目链接:西安: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 }