1. 程式人生 > >Codeforces 338E Optimize! 線段樹

Codeforces 338E Optimize! 線段樹

class optimize eps turn 數組 sign 維護 pull clas

Optimize!

這個題目代碼看了我半天。。

我們把終點關註在b數組, 我們先將b[ i ] 變成 h - b[ i ]並排好序, 對於一個a[ j ]來說如果它能和b[ i ]匹配, 那麽它能和b[ k ], k < i, 匹配。

什麽情況下能匹配成功呢, 就是b數組中 前 i 個數至少能和 len - i + 1, 個數匹配,這個隨便想想就知道, 或者通過霍爾定理也能很快得到,

那麽就能用線段樹取維護了。

#include<bits/stdc++.h>
#define LL long long
#define LD long double
#define
ull unsigned long long #define fi first #define se second #define mk make_pair #define PLL pair<LL, LL> #define PLI pair<LL, int> #define PII pair<int, int> #define SZ(x) ((int)x.size()) #define ALL(x) (x).begin(), (x).end() #define fio ios::sync_with_stdio(false); cin.tie(0); using
namespace std; const int N = 2e5 + 7; const int inf = 0x3f3f3f3f; const LL INF = 0x3f3f3f3f3f3f3f3f; const int mod = 998244353; const double eps = 1e-8; const double PI = acos(-1); template<class T, class S> inline void add(T& a, S b) {a += b; if(a >= mod) a -= mod;} template
<class T, class S> inline void sub(T& a, S b) {a -= b; if(a < 0) a += mod;} template<class T, class S> inline bool chkmax(T& a, S b) {return a < b ? a = b, true : false;} template<class T, class S> inline bool chkmin(T& a, S b) {return a > b ? a = b, true : false;} int n, len, h; int a[N], b[N], c[N]; struct SegmentTree { #define lson l, mid, rt << 1 #define rson mid + 1, r, rt << 1 | 1 int mx[N << 2], lazy[N << 2]; inline void pull(int rt) { mx[rt] = max(mx[rt << 1], mx[rt << 1 | 1]); } inline void push(int rt) { if(lazy[rt]) { mx[rt << 1] += lazy[rt]; mx[rt << 1 | 1] += lazy[rt]; lazy[rt << 1] += lazy[rt]; lazy[rt << 1 | 1] += lazy[rt]; lazy[rt] = 0; } } void build(int l, int r, int rt) { if(l == r) { mx[rt] = len - l + 1; return; } int mid = l + r >> 1; build(lson); build(rson); pull(rt); } void update(int L, int R, LL val, int l, int r, int rt) { if(R < l || r < L || R < L) return; if(L <= l && r <= R) { mx[rt] += val; lazy[rt] += val; return; } push(rt); int mid = l + r >> 1; update(L, R, val, lson); update(L, R, val, rson); pull(rt); } } Tree; int main() { scanf("%d%d%d", &n, &len, &h); for(int i = 1; i <= len; i++) { scanf("%d", &b[i]); b[i] = h - b[i]; } sort(b + 1, b + 1 + len); for(int i = 1; i <= n; i++) { scanf("%d", &a[i]); c[i] = upper_bound(b + 1, b + 1 + len, a[i]) - b - 1; } Tree.build(1, len, 1); for(int i = 1; i <= len; i++) Tree.update(1, c[i], -1, 1, len, 1); int ans = 0; for(int i = 1; i + len - 1 <= n; i++) { ans += Tree.mx[1] <= 0; Tree.update(1, c[i], 1, 1, len, 1); if(i + len <= n) Tree.update(1, c[i + len], -1, 1, len, 1); } printf("%d\n", ans); return 0; } /* */

Codeforces 338E Optimize! 線段樹