[CF1373G] Pawns

[题目链接]

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\n" , query(1 , 1 , 2 * N , 1 , *s.rbegin() + 1) - N);
 	 }
     return 0;
}
posted @ 2021-02-23 17:43  evenbao  阅读(95)  评论(0编辑  收藏  举报