[题目链接]
http://codeforces.com/contest/1373/problem/G
[题解]
首先不妨求出对于每个棋子其所能到达的最近的列 (a_{i} = y_{i} + |x_{i} - k|)。
建立二分图模型 , 将 (i) 向 ([a_{i} , s]) 内的点连边。
根据 (Hall) 定理 , (s) 合法当且仅当对于任意 (j) 满足 ([j , s]) 区间内的和 (leq s - j + 1)。
如果令 ([j , s]) 内的和为 (p_{j}) , 要求的是 (p_{j} + j - 1 leq s)。
线段树维护区间最值即可。
时间复杂度 : (O(NlogN))
[代码]
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef pair < int , int > pii;
#define rep(i , l , r) for (int i = (l); i < (r); ++i)
#define mp make_pair
const int MN = 2e6 + 5 , INF = 2e9;
int N , M , K , mx[MN << 2] , tg[MN << 2] , cnt[MN];
multiset < int > s;
map < pii , int > st;
inline void pushup(int now) {
mx[now] = max(mx[now << 1] , mx[now << 1 | 1]);
}
inline void build(int now , int l , int r) {
if (l == r) {
mx[now] = l - 1;
return;
}
int mid = l + r >> 1;
build(now << 1 , l , mid) , build(now << 1 | 1 , mid + 1 , r);
pushup(now);
assert(mx[now] == r - 1);
}
inline void pushdown(int now) {
mx[now << 1] += tg[now] , mx[now << 1 | 1] += tg[now];
tg[now << 1] += tg[now] , tg[now << 1 | 1] += tg[now];
tg[now] = 0; return;
}
inline void modify(int now , int l , int r , int ql , int qr , int val) {
if (l != r) pushdown(now);
if (l == ql && r == qr) {
mx[now] += val; tg[now] += val;
return;
}
int mid = l + r >> 1;
if (mid >= qr) modify(now << 1 , l , mid , ql , qr , val);
else if (mid + 1 <= ql) modify(now << 1 | 1 , mid + 1 , r , ql , qr , val);
else modify(now << 1 , l , mid , ql , mid , val) , modify(now << 1 | 1 , mid + 1 , r , mid + 1 , qr , val);
pushup(now);
}
inline int query(int now , int l , int r , int ql , int qr) {
if (ql > qr) return 0;
if (l == ql && r == qr) return mx[now];
int mid = l + r >> 1; pushdown(now);
if (mid >= qr) return query(now << 1 , l , mid , ql , qr);
else if (mid + 1 <= ql) return query(now << 1 | 1, mid + 1 , r , ql , qr);
else return max(query(now << 1 , l , mid , ql , mid) , query(now << 1 | 1 , mid + 1 , r , mid + 1 , qr));
}
int main() {
scanf("%d%d%d" , &N , &K , &M); build(1 , 1 , 2 * N);
s.insert(N);
for (int i = 1; i <= M; ++i) {
int x , y; scanf("%d%d" , &x , &y);
int val = 1 , a = y + abs(x - K);
if (st[mp(x , y)]) {
s.erase(s.find(a));
val = -1;
} else {
s.insert(a);
val = 1;
}
st[mp(x , y)] ^= 1;
modify(1 , 1 , 2 * N , 1 , a , val);
printf("%d
" , query(1 , 1 , 2 * N , 1 , *s.rbegin() + 1) - N);
}
return 0;
}