题解:AT_abc356_f [ABC356F] Distance Component Size Query
明显可以分别二分往 Check 可以通过区间询问差距的最大值是否超过
而对于区间的询问,使用线段树,先离线从小到大分配线段树每个叶子对应哪个数,修改结点时把线段树叶子上的布尔标记取反,难点就只剩 pushup 了。
node pushup(node x,node y)
{
node ans={x.tot+y.tot,0,0,0};
if(x.tot==0||y.tot==0)//如果有一边没有节点,则直接用另一边
{
if(x.tot==0)ans.res=y.res;
else if(y.tot==0)ans.res=x.res;
}
else ans.res=max(max(x.res,y.res),abs(x.rnum-y.lnum));//用两段答案和中间更新最大值
if(x.tot==0)ans.lnum=y.lnum;
else ans.lnum=x.lnum;
if(y.tot==0)ans.rnum=x.rnum;
else ans.rnum=y.rnum;
return ans;
}
Code
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=2e5+5;
int q,k;
struct node
{
int tot,res,lnum,rnum;
};
unordered_map<long long,int>id;
struct que
{
int op,x,idx;
}t[N];
bool cmp1(que x,que y)
{
return x.x<y.x;
}
bool cmp2(que x,que y)
{
return x.idx<y.idx;
}
struct tree
{
#define lson l,mid,num<<1
#define rson mid+1,r,num<<1|1
#define get_mid int mid=(l+r)>>1
node a[N<<2];
node pushup(node x,node y)
{
node ans={x.tot+y.tot,0,0,0};
if(x.tot==0||y.tot==0)
{
if(x.tot==0)ans.res=y.res;
else if(y.tot==0)ans.res=x.res;
}
else ans.res=max(max(x.res,y.res),abs(x.rnum-y.lnum));
if(x.tot==0)ans.lnum=y.lnum;
else ans.lnum=x.lnum;
if(y.tot==0)ans.rnum=x.rnum;
else ans.rnum=y.rnum;
return ans;
}
void build(int l,int r,int num)
{
if(l==r)
{
a[num]={0,0,0,0};
return;
}
get_mid;
build(lson),build(rson);
a[num]=pushup(a[num<<1],a[num<<1|1]);
}
void update(int pos,int x,int l,int r,int num)
{
if(l==r&&l==pos)
{
a[num]={!a[num].tot,0,x,x};
return;
}
get_mid;
if(pos<=mid)update(pos,x,lson);
if(pos>mid)update(pos,x,rson);
a[num]=pushup(a[num<<1],a[num<<1|1]);
}
node query(int L,int R,int l,int r,int num)
{
if(L<=l&&r<=R)return a[num];
get_mid;
if(L<=mid&&R>mid)return pushup(query(L,R,lson),query(L,R,rson));
if(L<=mid)return query(L,R,lson);
if(R>mid)return query(L,R,rson);
}
}tr;
signed main()
{
cin>>q>>k;
int tot=0;
for(int i=1;i<=q;i++)
{
cin>>t[i].op>>t[i].x;
t[i].idx=i;
}
sort(t+1,t+1+q,cmp1);
for(int i=1;i<=q;i++)
{
if(t[i].op==2)continue;
if(!id.count(t[i].x))id[t[i].x]=++tot;
}
sort(t+1,t+1+q,cmp2);
tr.build(1,tot,1);
for(int i=1;i<=q;i++)
{
if(t[i].op==1)tr.update(id[t[i].x],t[i].x,1,tot,1);
else
{
int ans1=0,ans2=0,l=id[t[i].x],r=tot;
while(l<=r)
{
int mid=l+r>>1;
node tt=tr.query(id[t[i].x],mid,1,tot,1);
if(tt.res<=k)
{
ans1=tt.tot;
l=mid+1;
}
else r=mid-1;
}
l=1,r=id[t[i].x];
while(l<=r)
{
int mid=l+r>>1;
node tt=tr.query(mid,id[t[i].x],1,tot,1);
if(tt.res<=k)
{
ans2=tt.tot;
r=mid-1;
}
else l=mid+1;
}
cout<<ans1+ans2-1<<endl;
}
}
}