1. 程式人生 > 實用技巧 >2020牛客暑期多校訓練營(第二場)Greater and Greater

2020牛客暑期多校訓練營(第二場)Greater and Greater

題目連結

https://ac.nowcoder.com/acm/contest/5667/G

題目大意

給你一個長度為 N 的陣列 A 和一個長度為 M 的陣列 B

問 A 中存在多少個長度為 M 的子串使得 Ai >= B1 , Ai+1 >= B2 , ... , Ai+m >= Bm

解題思路

樣例為N = 6 , M = 3 , A = { 1,4,2,8,5,7} , B = {2,3,3}

我們對每個 Bj 求一個長度為 N 的 bitset ,設為Bis [ j ]

其意義為 若 Ai 大於等於 Bj , 則 Bis[ pos[ Ai ] ] = 1 , 否則為 0

那麼對應樣例我們得到的 Bis 分別為

容易發現若存在這麼一條右斜線 , 可以從 1 走到 m , 則 ans ++

我們將第 J 個 Bis[j] 左移 J - 1位 , 得到

於是原來的斜線就變成了豎線

那麼我們只要把所有的 Bis[j] 左移之後進行 & 運算 , 然後統計最後的結果有多少 1 即可

那麼 Bis [j] 怎麼求呢?

我們可以先對 A , B 進行降序排序 , 然後執行下圖操作(畫的有點醜hh)

AC_Code

#include<bits/stdc++.h>
#define fi first
#define se second
using namespace std;
const int
N = 2e5 + 10; pair<int , int>a[N] , b[N]; bitset<N>ans , now; signed main() { ios::sync_with_stdio(false) , cin.tie(0) , cout.tie(0); int n , m ; cin >> n >> m ; for(int i = 1 ; i <= n ; i ++) cin >> a[i].fi , a[i].se = i; for(int i = 1 ; i <= m ; i ++) cin >> b[i].fi , b[i].se = i; sort(a
+ 1 , a + 1 + n , greater<pair<int , int>>()); sort(b + 1 , b + 1 + m , greater<pair<int , int>>()); ans.set() , now.reset(); int pos = 1; for(int i = 1 ; i <= m ; i ++) { while(pos <= n && a[pos].fi >= b[i].fi) now.set(a[pos].se) , pos ++ ; ans &= now >> b[i].se; } cout << ans.count() << '\n'; return 0; }