G. Pawns
time limit per test
3 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output
You are given a chessboard consisting of nn rows and nn columns. Rows are numbered from bottom to top from 11 to nn. Columns are numbered from left to right from 11 to nn. The cell at the intersection of the xx-th column and the yy-th row is denoted as (x,y)(x,y). Furthermore, the kk-th column is a special column.
Initially, the board is empty. There are mm changes to the board. During the ii-th change one pawn is added or removed from the board. The current board is good if we can move all pawns to the special column by the followings rules:
The current board may not always be good. To fix it, you can add new rows to the board. New rows are added at the top, i. e. they will have numbers n+1,n+2,n+3,…n+1,n+2,n+3,….
After each of mm changes, print one integer — the minimum number of rows which you have to add to make the board good.
Input
The first line contains three integers nn, kk and mm (1≤n,m≤2⋅105;1≤k≤n1≤n,m≤2⋅105;1≤k≤n) — the size of the board, the index of the special column and the number of changes respectively.
Then mm lines follow. The ii-th line contains two integers xx and yy (1≤x,y≤n1≤x,y≤n) — the index of the column and the index of the row respectively. If there is no pawn in the cell (x,y)(x,y), then you add a pawn to this cell, otherwise — you remove the pawn from this cell.
Output
After each change print one integer — the minimum number of rows which you have to add to make the board good.
Example
input
Copy
5 3 5 4 4 3 5 2 4 3 4 3 5
output
Copy
0 1 2 2 1
题意:给你一个n*n(<=2e5)的棋盘,其中第k(<=n)列是特殊的,进行m(<=2e5)次操作。
每次操作会给出一个坐标(x,y)表示第x列 第y行,若该点没有棋子则放一个,否则将该点的棋子拿走。
每次操作之后,你要在脑中想,如果每个棋子(x,y)只能移动到 (x-1,y+1)、(x,y+1)、 (x+1,y+1),移动次数不限制,那么至少需要增加多少行,才能使得所有棋子都可以移动到第k列?每次操作之后输出一个数表示答案。
分析:感觉好难想到啊。因为棋子每移动一步,行数必定+1,所以我们可以计算出该棋子移动到第k列时最小的行数pos,这个棋子可以移动到第k列中任何行数>=pos的位置。
如果只是一次查询,那么我们只需要先记录所有的pos上棋子的数量,最后从第k列第一行往下扫,直到所有的棋子都获得一个不同的行标。但是由于是m次查询,因此我们就需要维护一些东西。
最巧妙的地方:对于第k列某行pos,如果它前面的行足够摆下pos-1行之前的棋子,那么pos位置的棋子数量就决定了pos这个位置需要往下增加多少行,最大的pos的棋子数量也就确定了最后的答案。如果它前面的行不足以摆下pos-1行之前的棋子,那么实际上第pos的位置上的棋子个数(对答案的影响)相当于放到第pos-1的位置了。
因此,初始化下标i=[1,n+n]的值为i-1(注意pos最大为2*n-1) 对于每颗棋子,对应第k列位置为pos,我们就把下标[1,pos]对应的值都+1,这样每一个下标的值都表示从这一行开始往下摆放所有后面的棋子的最终行数了。用线段树维护一下,取个最大值就可以了。注意0时的特殊处理。注意数组大小。
代码:
#include
#define ll long long
#define inf 0x3f3f3f3f
#define mst(head,x,n) memset(head+1,x,n*sizeof(head[0]))
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define dep(i,a,b) for(int i=(a);i>=(b);i--)
#define lson rt<<1
#define rson rt<<1|1
using namespace std;
const int maxn=4e5+5;
//const double pi=acos(-1.0);
//const double eps=1e-9;
//const ll mo=1e9+7;
int n,m,k;
int a[maxn<<2],c[maxn<<2],num[maxn<<2];
int ans,tmp,cnt;
int flag;
template
inline void read(T &X){
X=0;int w=0; char ch=0;
while(!isdigit(ch)) {w|=ch=='-';ch=getchar();}
while(isdigit(ch)) X=(X<<3)+(X<<1)+(ch^48),ch=getchar();
if(w) X=-X;
}
void pu(int rt){
c[rt]=max(c[lson],c[rson]);
}
void pd(int rt){
if(a[rt]){
c[lson]+=a[rt];
c[rson]+=a[rt];
a[lson]+=a[rt];
a[rson]+=a[rt];
a[rt]=0;
}
}
void build(int rt,int l,int r){
if(l==r){
c[rt]=l-1;
a[rt]=0;
return ;
}
int mid=(l+r)>>1;
build(lson,l,mid);
build(rson,mid+1,r);
pu(rt);
}
void update(int rt,int l,int r,int L,int R,int v){
if(L<=l&&r<=R){
a[rt]+=v;
c[rt]+=v;
return ;
}
pd(rt);
int mid=(l+r)>>1;
if(L<=mid) update(lson,l,mid,L,R,v);
if(R>mid) update(rson,mid+1,r,L,R,v);
pu(rt);
}
int query(int rt,int l,int r,int L,int R){
if(L<=l&&r<=R){
return c[rt];
}
pd(rt);
int mid=(l+r)>>1;
int ans=0;
if(L<=mid) ans=max(ans,query(lson,l,mid,L,R));
if(R>mid) ans=max(ans,query(rson,mid+1,r,L,R));
//pu(rt);
return ans;
}
int main(){
#ifdef ONLINE_JUDGE
#else
freopen("D:/Temp/in.txt", "r", stdin);
#endif
int T,cas=1;
//read(T);
//while(T--)
{
read(n);read(k);read(m);
set >st;
setlst;
build(1,1,n+n);
rep(i,1,m){
int x,y;
read(x);read(y);
int pos=y+abs(x-k);
pairp=make_pair(x,y);
if(st.count(p)){
num[pos]--;
if(num[pos]==0) lst.erase(pos);
st.erase(p);
update(1,1,n+n,1,pos,-1);
}
else {
st.insert(p);
num[pos]++;
if(num[pos]==1) lst.insert(pos);
update(1,1,n+n,1,pos,1);
}
//cout<<"debug: "<