Description
思路
看了cf的题解,没想到这么的简单巧妙,tql
如果一个棋子在(x, y),那么它到k列的最小纵坐标i = y + abs(x - k)。所以就可以统计第k列的每一行有将多少枚棋子。
假设有r×m的棋盘,设f(j)为第k列、第j行及以上(j<=r)将有多少枚棋子。那么棋盘r×m可以放得下所有棋子的充要条件是f(j) <= r - j + 1。
变形一下就是f(j) + j - r - 1 <= 0。所以对每一个j,维护一个f(j) + j - n - 1,这个值就是当前所需要加的行数。每次更新棋子对前缀区间+1或-1,答案就是求[1, maxi]区间的最大值(maxi是所有在棋盘中的棋子的最大的i)。显然线段树可以解决这个问题。
注意,有些棋子的i可能大于n,所以要开2n的线段树。
#include <iostream>
#include <cstdio>
#include <queue>
#include <algorithm>
#include <map>
#include <set>
#include <vector>
#include <cstring>
#include <string>
#include <stack>
#include <deque>
#include <cmath>
#include <iomanip>
#include <cctype>
#define endl '
'
#define IOS
std::ios::sync_with_stdio(0);
cout.tie(0);
cin.tie(0);
#define FILE freopen("..//data_generator//in.txt", "r", stdin), freopen("res.txt", "w", stdout)
#define FI freopen("..//data_generator//in.txt", "r", stdin)
#define FO freopen("res.txt", "w", stdout)
#define pb cpush_back
#define mp make_pair
#define seteps(N) fixed << setprecision(N)
typedef long long ll;
using namespace std;
/*-----------------------------------------------------------------*/
#define INF 0x3f3f3f3f
const int N = 2e6 + 10;
const int M = 1e9 + 7;
const double eps = 1e-8;
int lazy[N];
int maxn[N];
int n;
void pushdown(int rt) {
if(lazy[rt] ){
lazy[rt << 1] += lazy[rt];
lazy[rt << 1 | 1] += lazy[rt];
maxn[rt << 1] += lazy[rt];
maxn[rt << 1 | 1] += lazy[rt];
lazy[rt] = 0;
}
}
void pushup(int rt) {
maxn[rt] = max(maxn[rt << 1], maxn[rt << 1 | 1]);
}
void build(int l, int r, int rt) {
if(l == r) {
maxn[rt] = l + 0 - n - 1;
lazy[rt] = 0;
return ;
}
int mid = (l + r) / 2;
build(l, mid, rt << 1);
build(mid + 1, r, rt << 1 | 1);
pushup(rt);
}
int query(int l, int r, int L, int R ,int rt) {
if(L <= l && R >= r) {
return max(0, maxn[rt]);
}
int res = 0;
int mid = (l + r) / 2;
pushdown(rt);
if(mid >= L) res = max(res, query(l, mid, L, R, rt << 1));
if(mid < R) res = max(res, query(mid + 1, r, L, R, rt << 1 | 1));
pushup(rt);
return res;
}
void update(int l, int r, int L, int R, int rt, int val) {
if(L <= l && R >= r) {
maxn[rt] += val;
lazy[rt] += val;
return ;
}
pushdown(rt);
int mid = (l + r) / 2;
if(mid >= L) update(l, mid, L, R , rt << 1, val);
if(mid < R) update(mid + 1, r, L, R , rt << 1 | 1, val);
pushup(rt);
}
typedef pair<int, int> PII;
set<PII> ex;
int cnt[N];
set<int> mx;
int main() {
IOS;
int k, m;
cin >> n >> k >> m;
build(1, 2 * n , 1);
while(m--) {
int x, y;
cin >> x >> y;
int val;
int tar = y + abs(x - k);
if(ex.count(mp(x, y))) {
ex.erase(mp(x, y));
cnt[tar]--;
if(!cnt[tar]) mx.erase(tar);
update(1, 2 * n, 1, tar ,1, -1);
} else {
ex.insert(mp(x, y));
cnt[tar]++;
mx.insert(tar);
update(1, 2 * n, 1, tar ,1, 1);
}
if(mx.empty()) cout << 0 << endl; //注意可能棋盘上没有棋子了
else cout << query(1, 2 * n, 1, *mx.rbegin(), 1) << endl; //rbegin技巧,set变优先队列
}
}