专栏文章
P14447 [ICPC 2025 Xi'an R] Azalea Garden
P14447题解参与者 1已保存评论 0
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 0 条
- 当前快照
- 1 份
- 快照标识符
- @mina4bi6
- 此快照首次捕获于
- 2025/12/01 23:03 3 个月前
- 此快照最后确认于
- 2025/12/01 23:03 3 个月前
此篇为 dmy 比赛复盘。
显然剩下最小可以转为击败最多。
把 最大的拿出来击败其他的肯定是最优的,不妨令为 ,如果可以击败 个,则答案肯定为 或 ,即这个 也可以被打败,考虑以下情况:
- 。则 不能被击败,答案为 。
- 令不能击败的 中的最大值为 ,如果有 ,答案为 。
- 再能击败中找出一个序列 ,其中 为 的最后一项,使得对于任意 ,,即前者能击败后者,然后有 ,这样答案为 。 我们思考第三种情况,发现向这种环环紧扣的结构可以转换为若干区间,使得它们的并是一段连续的区间。具体地,把每组 转化为区间 ,若最后存在其中若干区间的并能完全覆盖 ,则答案可行。线段树维护即可。
具体地,将值离散化,值域线段树下标为防御值 ,维护区间中尽量长的并,即可以维护 ,如果 ,则左端点可以为 ,否则取 最大值。特殊地,如果 ,则左端点直接为 ,不用取 原因是 一定不小于 。然后我们可以在是指线段树统计,唯一特殊的地方是,当 时,我们在统计 不可以击败的会算上自己,而自己本来就不能被击败,故直接返回即可。
CPP#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;
}
相关推荐
评论
共 0 条评论,欢迎与作者交流。
正在加载评论...