P14447 [ICPC 2025 Xi'an R] Azalea Garden
此篇为 dmy 比赛复盘。
显然剩下最小可以转为击败最多。
把
-
- 令不能击败的
a_j 中的最大值为A ,如果有b_i\leq A ,答案为sum+1 。 - 再能击败中找出一个序列
k ,其中i 为k 的最后一项,使得对于任意i ,b_{k_{i+1}}\leq a_{k_i} ,即前者能击败后者,然后有b_1\leq A ,这样答案为sum+1 。 我们思考第三种情况,发现向这种环环紧扣的结构可以转换为若干区间,使得它们的并是一段连续的区间。具体地,把每组a_i,b_i 转化为区间[b_i,a_i] ,若最后存在其中若干区间的并能完全覆盖[A,b_i] ,则答案可行。线段树维护即可。
具体地,将值离散化,值域线段树下标为防御值
#include <bits/stdc++.h>
using namespace std;
// #define int long long
#define pb push_back
#define eb emplace_back
#define all(x) (x).begin(),(x).end()
#define fi first
#define se second
#define SZ(x) ((int)(x).size())
typedef vector<int> VI;
typedef long long ll;
typedef pair<int,int> PII;
const ll MOD=998244353;
// head
const int N=4e5+5,M=2e6+5,INF=2e9;
int a[N],b[N];
int d[M],tot;
struct node{int v,x,y;}que[N];
#define mid ((l+r)>>1)
#define ls(x) (x<<1)
#define rs(x) (x<<1|1)
multiset<int> S[M];
struct node1{int sum,mx,mn;};
struct Seg_tree
{
node1 ans[M<<2];
node1 merge(node1 l,node1 r)
{
node1 now;
now.sum=l.sum+r.sum;
if(l.mx>=r.mx) now.mx=l.mx,now.mn=l.mn;
else now.mx=r.mx,now.mn=(l.mx>=r.mn?l.mn:r.mn);
return now;
}
void push_up(int pos)
{
ans[pos]=merge(ans[ls(pos)],ans[rs(pos)]);
}
void upd(int pos,int x)
{
ans[pos].mx=-INF,ans[pos].mn=INF,ans[pos].sum=S[x].size();
if(S[x].size()) ans[pos].mx=*S[x].rbegin(),ans[pos].mn=x;
}
void build(int pos,int l,int r)
{
if(l==r){
upd(pos,l);
return ;
}
build(ls(pos),l,mid);
build(rs(pos),mid+1,r);
push_up(pos);
}
void modify(int pos,int l,int r,int x)
{
if(l==r) {upd(pos,l);return ;}
if(x<=mid) modify(ls(pos),l,mid,x);
else modify(rs(pos),mid+1,r,x);
push_up(pos);
}
node1 query(int pos,int l,int r,int ql,int qr)
{
if(ql<=l&&r<=qr) return ans[pos];
if(qr<=mid) return query(ls(pos),l,mid,ql,qr);
else if(ql>mid) return query(rs(pos),mid+1,r,ql,qr);
return merge(query(ls(pos),l,mid,ql,qr),query(rs(pos),mid+1,r,ql,qr));
}
}tree;
int work()
{
int x=tree.ans[1].mx,y=tree.ans[1].mn;
if(x==tot) return 1;
node1 tmp=tree.query(1,1,tot,x+1,tot);
if(x<y) return tmp.sum;
if(y<=tmp.mx) return tmp.sum;
return tmp.sum+1;
}
signed main()
{
cin.tie(nullptr);
ios::sync_with_stdio(false);
int n,q;cin>>n>>q;
for(int i=1;i<=n;i++) {cin>>a[i]>>b[i];d[++tot]=a[i],d[++tot]=b[i];}
for(int i=1;i<=q;i++) {cin>>que[i].v>>que[i].x>>que[i].y;d[++tot]=que[i].x,d[++tot]=que[i].y;}
sort(d+1,d+tot+1);tot=unique(d+1,d+tot+1)-d-1;
for(int i=1;i<=n;i++) a[i]=lower_bound(d+1,d+tot+1,a[i])-d,b[i]=lower_bound(d+1,d+tot+1,b[i])-d;
for(int i=1;i<=q;i++) que[i].x=lower_bound(d+1,d+tot+1,que[i].x)-d,que[i].y=lower_bound(d+1,d+tot+1,que[i].y)-d;
for(int i=1;i<=n;i++) S[b[i]].insert(a[i]);
tree.build(1,1,tot);
cout<<work()<<'\n';
for(int i=1;i<=q;i++){
S[b[que[i].v]].erase(S[b[que[i].v]].find(a[que[i].v]));
tree.modify(1,1,tot,b[que[i].v]);
a[que[i].v]=que[i].x,b[que[i].v]=que[i].y;
S[b[que[i].v]].insert(a[que[i].v]);
tree.modify(1,1,tot,b[que[i].v]);
cout<<work()<<'\n';
}
for(int i=1;i<=n;i++) S[b[i]].clear();
tot=0;
}