专栏文章
题解:P10208 [JOI 2024 Final] 礼物交换 / Gift Exchange
P10208题解参与者 1已保存评论 0
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 0 条
- 当前快照
- 1 份
- 快照标识符
- @min4shr3
- 此快照首次捕获于
- 2025/12/01 20:34 3 个月前
- 此快照最后确认于
- 2025/12/01 20:34 3 个月前
题意可以变为询问区间内有没有二分图完美匹配。
考虑使用霍尔定理。
将这些 排序后形如。
考虑什么样的情况是不合法的。
把所有的 当作左部点。
贪心的想一下。
首先以 结尾的前缀肯定是相比 结尾的更劣。
对于这样的一个前缀,在保证选最右侧的 的时候,最劣的子集情况就是全选所有的 ,因为 的个数不会改变。
即 。
但是 不能连 。
推理一下。
只有在 的情况下无解。
这对相邻的 真是对苦命鸳鸯啊!
考虑一下就是 不和其他区间相交。
维护出每个 左边第一个与其相交的,右边第一个与其相交的,离线下来扫描线即可。
CPP#include<bits/stdc++.h>
#define INF 1000000000
using namespace std;
int read(){
int p=0;char ch=getchar();
while(ch<'0'||ch>'9') ch=getchar();
while(ch>='0'&&ch<='9') p=(p<<1)+(p<<3)+ch-'0',ch=getchar();
return p;
}
const int N=5e5+5;
struct seg2{
int mx[N*4],tag[N*4];
void pd(int id){
if(tag[id]==INF) return;
tag[id<<1]=min(tag[id<<1],tag[id]);
tag[id<<1|1]=min(tag[id<<1|1],tag[id]);
mx[id<<1]=min(mx[id<<1],tag[id]);
mx[id<<1|1]=min(mx[id<<1|1],tag[id]);
tag[id]=INF;
}
void change(int L,int R,int l,int r,int id,int v){
if(L<=l&&r<=R){
mx[id]=v;
tag[id]=v;
return;
}
pd(id);
int mid=l+r>>1;
if(L<=mid) change(L,R,l,mid,id<<1,v);
if(R>mid) change(L,R,mid+1,r,id<<1|1,v);
mx[id]=min(mx[id<<1],mx[id<<1|1]);
}
int query(int L,int R,int l,int r,int id){
if(L<=l&&r<=R) return mx[id];
pd(id);
int mid=l+r>>1;
if(L<=mid&&R>mid) return min(query(L,R,l,mid,id<<1),query(L,R,mid+1,r,id<<1|1));
else if(L<=mid) return query(L,R,l,mid,id<<1);
else return query(L,R,mid+1,r,id<<1|1);
}
}t3;
struct seg{
int mx[N*8],tag[N*8];
void pd(int id){
if(!tag[id]) return;
tag[id<<1]=max(tag[id<<1],tag[id]);
tag[id<<1|1]=max(tag[id<<1|1],tag[id]);
mx[id<<1]=max(mx[id<<1],tag[id]);
mx[id<<1|1]=max(mx[id<<1|1],tag[id]);
tag[id]=0;
}
void change(int L,int R,int l,int r,int id,int v){
if(L<=l&&r<=R){
mx[id]=v;
tag[id]=v;
return;
}
pd(id);
int mid=l+r>>1;
if(L<=mid) change(L,R,l,mid,id<<1,v);
if(R>mid) change(L,R,mid+1,r,id<<1|1,v);
mx[id]=max(mx[id<<1],mx[id<<1|1]);
}
int query(int L,int R,int l,int r,int id){
if(L<=l&&r<=R) return mx[id];
pd(id);
int mid=l+r>>1;
if(L<=mid&&R>mid) return max(query(L,R,l,mid,id<<1),query(L,R,mid+1,r,id<<1|1));
else if(L<=mid) return query(L,R,l,mid,id<<1);
else return query(L,R,mid+1,r,id<<1|1);
}
}t1,t2;
int a[N],b[N];
int n,m;
int ans[N];
int pl[N],pr[N];
vector<int> v1[N];
vector<pair<int,int> > q[N];
int main(){
n=read();
for(int i=1;i<=n;i++) a[i]=read();
for(int i=1;i<=n;i++) b[i]=read();
for(int i=1;i<=n;i++){
pl[i]=t1.query(b[i],a[i],1,2*n,1);
t1.change(b[i],a[i],1,2*n,1,i);
}
for(int i=n;i;i--){
pr[i]=n-t2.query(b[i],a[i],1,2*n,1)+1;
t2.change(b[i],a[i],1,2*n,1,n-i+1);
}
for(int i=0;i<=500000*4;i++) t3.tag[i]=t3.mx[i]=INF;
for(int i=1;i<=n;i++){
v1[pr[i]].push_back(i);
}
for(int i=1;i<=n;i++) t3.change(i,i,1,n,1,pl[i]);
m=read();
for(int i=1;i<=m;i++){
int x=read(),y=read();
q[y].push_back({x,i});
}
for(int i=1;i<=n;i++){
for(int j:v1[i]){
t3.change(j,j,1,n,1,INF);
}
for(pair<int,int> j:q[i]){
int o=t3.query(j.first,i,1,n,1);
if(o>=j.first) ans[j.second]=1;
else ans[j.second]=0;
}
}
for(int i=1;i<=m;i++) if(ans[i]) puts("Yes");else puts("No");
return 0;
}
相关推荐
评论
共 0 条评论,欢迎与作者交流。
正在加载评论...