题目
给出两个序列,求出第二个序列在第一个序列中能够匹配的次数,匹配是指每个位置都小于等于第一个序列的相应位置
我还以为是kmp魔改…
从样例来讲,我们先求出
串中每个位置与
串中每个位置的相对大小,为1则表示符合,为0表示不符合
1 4 2 8 5 7
2 3 3
那么相对于第二个串2,3,3来说,相对大小就是
(2) 0 1 1 1 1 1
(3) 0 1 0 1 1 1
(3) 0 1 0 1 1 1
我们假设可以匹配成功的位置起始点是
,那么就需要要求从第1个点的
到第
个点的
全为一,才可以,为了方便看,我们把每个串都向左平移一下,使得同一起始点的都在同一列中,那就是
这个时候,所有在同一列的都是同一个起始点,如果这个起始点所有位置都是1,则表示可以选,全都是1的判断,很明显可以用与运算来实现,可以采用
来操作
大致如下
sort(a + 1, a + n + 1, comp);
sort(b + 1, b + m + 1, comp);
res.set();// 全为1
tmp.reset();// 全为 0
for(int i = 1, j = 1; i <= m; ++ i) {
while(j <= n && a[j].fi >= b[i].fi) {//找出所有大于当前的下标
tmp.set(a[j ++].se);// 标记这个下标
}
res &= (tmp << (m - b[i].se));
}
cout << res.count() << endl;// 计算为1的数目
我们首先给两个数组都排个序从大到小,1同时记录下原本的位置,然后我们从大大小求出每一个大于 的位置的下标,由于b数组是从大到小排列,那么前面计算出来大于的数字,肯定可以大于后面,可以重复利用,
由于bitset的储存是从小到大(从右向左),所以上图中向右移动实际上就是bitset向左移
最后与完直接计算剩下的1的数目就可以了
pii a[maxn], b[maxm];
bitset<maxn> res, tmp;
bool comp (const pii& aa, const pii& bb) {
return aa.fi > bb.fi;
}
void solve (int& kase) {
int n, m; cin >> n >> m;
rep(i,1,n) {
a[i] = MP(read(), i);
}
rep(i,1,m) {
b[i] = MP(read(), i);
}
sort(a + 1, a + n + 1, comp);
sort(b + 1, b + m + 1, comp);
res.set();
tmp.reset();
for(int i = 1, j = 1; i <= m; ++ i) {
while(j <= n && a[j].fi >= b[i].fi) {
tmp.set(a[j ++].se);
}
res &= (tmp << (m - b[i].se));
}
cout << res.count() << endl;
}