[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
" , query(1 , 1 , 2 * N , 1 , *s.rbegin() + 1) - N);
 	 }
     return 0;
}
原文地址:https://www.cnblogs.com/evenbao/p/14437310.html