专栏文章
题解:P14426 [JOISC 2014] 稻草人 / Scarecrows
P14426题解参与者 2已保存评论 1
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 1 条
- 当前快照
- 1 份
- 快照标识符
- @min9rmf8
- 此快照首次捕获于
- 2025/12/01 22:53 3 个月前
- 此快照最后确认于
- 2025/12/01 22:53 3 个月前
唐题,为什么别的题解写那么长。
先按照 排序,然后 CDQ 分治。分治中按照 排序,用左边贡献右边。发现左边可以按照 坐标维护一个单调栈,右边点能匹配的左边点数量就在单调栈上二分一下。
CPP/*
2025.11.11
* Happy Zenith Noises *
*/
#include<bits/stdc++.h>
#define int long long
#define pb push_back
#define fi first
#define se second
using namespace std;
typedef pair<int,int>P;
const int MAXN=200005,inf=0x3f3f3f3f3f3f3f3f;
int n,ans,fs[MAXN];
P a[MAXN],b[MAXN];
struct que{
int h,t;
P q[MAXN];
void init(){h=0,t=1;}
void insert(P x){
while(h>=t&&q[h].fi<x.fi)h--;
q[++h]=x;
}
int ask(int x){
if(h<t)return 0;
int l=t,r=h;
while(l<r){
int mid=(l+r)>>1;
if(q[mid].se>=x)r=mid;
else l=mid+1;
}
if(q[l].se>=x)return h-l+1;
return 0;
}
}st;
struct BIT{
int f[MAXN];vector<int>gg;
void init(){for(int i:gg)f[i]=0;gg.clear();}
void add(int x,int t){for(;x<MAXN;x+=(x&-x))f[x]=max(f[x],t),gg.pb(x);}
int ask(int x){int ans=0;for(;x;x-=(x&-x))ans=max(ans,f[x]);return ans;}
}tr;
void solve(int l,int r){
if(l==r)return ;
int mid=(l+r)>>1;
solve(l,mid);solve(mid+1,r);
int tl=l,tr=mid+1;
::tr.init();st.init();
for(int i=l;i<=r;i++){
if(tr==r+1||tl<=mid&&a[tl].se<a[tr].se){
st.insert(a[tl]);
b[i]=a[tl++];
}
else{
ans+=st.ask(::tr.ask(a[tr].fi-1));
::tr.add(a[tr].fi,a[tr].se);b[i]=a[tr++];
}
}
for(int i=l;i<=r;i++)a[i]=b[i];
}
signed main(){
ios::sync_with_stdio(0);cin.tie(nullptr);
cin>>n;
for(int i=1;i<=n;i++)cin>>a[i].fi>>a[i].se,a[i].fi++,a[i].se++,fs[i]=a[i].fi;
sort(fs+1,fs+1+n);int tn=unique(fs+1,fs+1+n)-(fs+1);
for(int i=1;i<=n;i++)a[i].fi=lower_bound(fs+1,fs+1+tn,a[i].fi)-fs;
sort(a+1,a+1+n);
solve(1,n);
cout<<ans;
return 0;
}
相关推荐
评论
共 1 条评论,欢迎与作者交流。
正在加载评论...