篱莘龙 题解
今天联赛T2,并没想到做法。
从特殊性质入手,当有 \(a_i<b_i\) 时,把每个奶龙看作区间 \([a_i,b_i]\),互不攻击当且仅当所有选中的区间有交点。则用一个线段树维护区间加和区间最大值即可。
当 \(a_i>b_i\) 时,区间是 \([b_i,a_i]\),此时 \(a_i<b_j\) 且 \(a_j<b_i\) 矛盾,最多只能选 \(1\) 个。
考虑两种都有的情况,还是用一棵线段树维护区间最大值,如果要选一个 \([b_x,a_x]\),则要求一个普通奶龙的 \([a_i,b_i]\) 完全覆盖这个区间,而且它不能和任何普通奶龙的区间是不完全的覆盖,我们引入另外一棵线段树,支持单点修,区间查最小值及其位置,我们把每个特殊奶龙存在线段树其右端点的位置上,值为左端点。每一次加入一个新的普通奶龙时,他可能会和原有的特殊奶龙相交,我们就把这些特殊奶龙都删除掉,包括其在线段树 \(1\) 中单点的贡献。
当加入的是一个特殊奶龙,我们需要事先判断它是否已经和普通区间有交了,可以用一个树状数组,每一个位置存有几个端点,区间查即可。如果合法,就把 sgt2 的右端点位置赋值为左端点的值,把 sgt1 的右端点单点加上 \(1\)。
复杂度 \(O(n\log n)\)。
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define _int __int128
#define ull unsigned long long
#define pii pair<int,int>
#define fst first
#define scd second
#define pq priority_queue
#define mkp make_pair
#define popcount(x) __builtin_popcount(x)
#define endl '\n'
int T,o,n,k;
const int N = 1e6+10,inf=1e18;
int a[N],b[N];
int mx[N<<3],tag[N<<3];
struct node{
int mi,id;
}tr[N<<3];
set<int>s;
#define ls p<<1
#define rs p<<1|1
struct sgt1{
void pushup(int p){
mx[p]=max(mx[ls],mx[rs]);
}
void pushdown(int p){
if(tag[p]){
mx[ls]+=tag[p];mx[rs]+=tag[p];
tag[ls]+=tag[p];tag[rs]+=tag[p];
tag[p]=0;
}
}
void modify(int p,int l,int r,int ql,int qr,int v){
if(ql>qr)return;
if(ql<=l&&r<=qr){
mx[p]+=v;
tag[p]+=v;
return;
}
pushdown(p);
int mid=(l+r)/2;
if(ql<=mid)modify(ls,l,mid,ql,qr,v);
if(qr>mid)modify(rs,mid+1,r,ql,qr,v);
pushup(p);
}
}T1;
struct sgt2{
#define mi(p) tr[p].mi
#define id(p) tr[p].id
void pushup(int p){
if(mi(ls)<mi(rs))tr[p]=tr[ls];
else tr[p]=tr[rs];
}
void build(int p,int l,int r){
if(l==r){
id(p)=l;
mi(p)=inf;
return;
}
int mid=(l+r)/2;
build(ls,l,mid);build(rs,mid+1,r);
pushup(p);
}
void add(int p,int l,int r,int x,int v){
if(l==r){
mi(p)=v;
return;
}
int mid=(l+r)/2;
if(x<=mid)add(ls,l,mid,x,v);
else add(rs,mid+1,r,x,v);
pushup(p);
}
node query(int p,int l,int r,int ql,int qr){
if(ql<=l&&r<=qr){
return tr[p];
}
int mid=(l+r)/2;
if(qr<=mid)return query(ls,l,mid,ql,qr);
if(ql>mid)return query(rs,mid+1,r,ql,qr);
node lt=query(ls,l,mid,ql,qr),rt=query(rs,mid+1,r,ql,qr);
if(lt.mi<rt.mi)return lt;
else return rt;
}
}T2;
int lowbit(int x){
return x&(-x);
}
struct bit{
int t[N<<1];
void add(int p,int v){
for(int i=p;i<=2*n;i+=lowbit(i))t[i]+=v;
}
int ask(int p){
int res=0;
for(int i=p;i;i-=lowbit(i)){
res+=t[i];
}
return res;
}
}t3;
void solve(int x){
t3.add(x,1);
while(1){
node t=T2.query(1,1,2*n,x,2*n);
if(t.mi>=x)return;
T2.add(1,1,2*n,t.id,inf);
T1.modify(1,1,2*n,t.id,t.id,-1);
}
}
signed main(){
ios::sync_with_stdio(0);
cin.tie(0),cout.tie(0);
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i]>>b[i];
}
T2.build(1,1,2*n);
for(int i=1;i<=n;i++){
if(a[i]<=b[i]){
solve(a[i]);solve(b[i]);
T1.modify(1,1,2*n,a[i],b[i],1);
}else{
if(t3.ask(a[i])-t3.ask(b[i]-1)>0){
cout<<mx[1]<<endl;
continue;
}
T2.add(1,1,2*n,a[i],b[i]);
T1.modify(1,1,2*n,a[i],a[i],1);
}
cout<<mx[1]<<endl;
}
return 0;
}

浙公网安备 33010602011771号