1 条题解
-
0
一道好题,由于当初看第一篇题解被困扰了一段时间,因此特意在此解释说明。
首先,对于一个点对 (不妨假设 ),若 ,那就意味着两者永远无法交换顺序,这启示我们进行拓扑。
在不考虑复杂度的情况下,我们可以暴力的连边 表示在 放入之前 绝对无法填入。
考虑优化这个过程,首先我们不妨扫描线,求出每个节点的度数,即对于 ,。
扫描下标,数据结构维护权值即可。
现在考虑求解答案,显然每次对于当前的开头,我们需要找到一个 ,将 填入当前的开头。
如果将 填入,我们就需要将所有的和 有连边的 的 。
但是这是一个二维偏序的问题,不方便动态处理,但是第一篇题解直接选择使用朴素线段树维护,这是为什么呢?
考虑和 有连边的节点的特性,即 ,同时根据 之间的大小关系确定连边方向。
但是注意到,当 被删除的时候,所有连向他的 也一定被删除了,而剩余的 的节点一定是 的关系。
因此我们直接朴素线段树维护即可,每次找出最小值,因为一定有解,所以最小值一定是 。然后线段树更新区间。
#include<bits/stdc++.h> #define fi first #define se second #define ll long long #define make make_pair #define pii pair<int,int> #define N 100005 #define lb(x) (x&(-x)) #define ls (now<<1) #define rs (now<<1|1) using namespace std; int read() { int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } int n,k,a[N],bit[N],w[N],tot,deg[N],lz[N*4],ct[N],pos[N]; pii tr[N*4]; void add(int x,int w) { for(;x<=n;x+=lb(x))bit[x]+=w; } int que(int x) { int ans=0; for(;x>=1;x-=lb(x))ans+=bit[x]; return ans; } void build(int now,int l,int r) { if(l==r) { tr[now]={deg[pos[l]],a[pos[l]]}; return ; } int mid=(l+r)>>1; build(ls,l,mid); build(rs,mid+1,r); tr[now]=min(tr[ls],tr[rs]); } void push(int now,int w) { lz[now]+=w; tr[now].fi+=w; } void down(int now) { push(rs,lz[now]); push(ls,lz[now]); lz[now]=0; } void midy(int now,int l,int r,int ql,int qr,int w) { if(ql>qr)return ; if(l>=ql&&r<=qr) { push(now,w); return ; } int mid=(l+r)>>1;down(now); if(mid>=ql)midy(ls,l,mid,ql,qr,w); if(mid<qr)midy(rs,mid+1,r,ql,qr,w); tr[now]=min(tr[ls],tr[rs]); } void del(int now,int l,int r) { if(l==r) { tr[now].fi=n+1; return ; } int mid=(l+r)>>1;down(now); if(tr[ls]==tr[now])del(ls,l,mid); else del(rs,mid+1,r); tr[now]=min(tr[ls],tr[rs]); } signed main() { n=read();k=read(); for(int i=1;i<=n;i++)a[i]=read(),w[i]=a[i]; sort(w+1,w+1+n); for(int i=1;i<=n;i++) { int l=lower_bound(w+1,w+1+n,a[i]-k)-w; int r=upper_bound(w+1,w+1+n,a[i]+k)-w-1; a[i]=lower_bound(w+1,w+1+n,a[i])-w; a[i]+=ct[a[i]];ct[a[i]]++; pos[a[i]]=i; deg[i]=(i-1)-que(r)+que(l-1); add(a[i],1); } build(1,1,n); for(int i=1,l,r;i<=n;i++) { int x=tr[1].se; cout<<w[x]<<"\n"; l=lower_bound(w+1,w+1+n,w[x]-k)-w-1; r=lower_bound(w+1,w+1+n,w[x]+k+1)-w; del(1,1,n); midy(1,1,n,1,l,-1); midy(1,1,n,r,n,-1); } return 0; }
- 1
信息
- ID
- 7656
- 时间
- 4000ms
- 内存
- 512MiB
- 难度
- 9
- 标签
- 递交数
- 12
- 已通过
- 5
- 上传者