NOIP 模拟 24block
题解 byzjφ
因为它要求大于它的且放在它前的数的个数要小于它的 key 值,所以先按 val 值排序,然后按 key 值排序,按顺序插入。
这样保证当前队列中已有的 val 值一定大于当前加入的,所以直接计算方案就行。
就是它的 val 和当前队列中的数的个数取 min,记得处理连续一段相同的情况
对于第二问,通过线段树实现
对于线段树,维护当前字典序最小的点,每次选出一个时删除当前点,并更新 val 值小于等于它的 key−1,当有 key 值为零的时,直接输出。
Code:
#include<bits/stdc++.h> #define ri register signed #define p(i) ++i using namespace std; namespace IO{ char buf[1<<21],*p1=buf,*p2=buf; #define gc() p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?(-1):*p1++; template<typename T>inline void read(T &x) { ri f=1;x=0;register char ch=gc(); while(ch<'0'||ch>'9') {if (ch=='-') f=0;ch=gc();}; while(ch>='0'&&ch<='9') {x=(x<<1)+(x<<3)+(ch^48);ch=gc();} x=f?x:-x; } } using IO::read; namespace nanfeng{ #define FI FILE *IN #define FO FILE *OUT template<typename T>inline T cmax(T x,T y) {return x>y?x:y;} template<typename T>inline T cmin(T x,T y) {return x>y?y:x;} typedef long long ll; static const int N=5e5+7,MOD=1e9+7,INF=1061109567; int K[N],V[N],p[N],pre[N],n; ll ans=1; inline int cmp(int x,int y) {return V[x]==V[y]?K[x]<K[y]:V[x]>V[y];} struct Seg{ #define ls(x) (x<<1) #define rs(x) (x<<1|1) struct segmenttree{int x,k,v,nk,nx,lz;}T[N<<2]; inline void up(int x) { int l=ls(x),r=rs(x); T[x].nk=cmin(T[l].nk,T[r].nk); if (T[x].nk!=INF) { if (T[l].nk<T[r].nk) T[x].nx=T[l].nx; else if (T[l].nk>T[r].nk) T[x].nx=T[r].nx; else { if (V[p[T[l].nx]]<V[p[T[r].nx]]) T[x].nx=T[l].nx; else if (V[p[T[l].nx]]>V[p[T[r].nx]]) T[x].nx=T[r].nx; else { if (K[p[T[l].nx]]<=K[p[T[r].nx]]) T[x].nx=T[l].nx; else if (K[p[T[l].nx]]>K[p[T[r].nx]]) T[x].nx=T[r].nx; } } } if (T[l].k<T[r].k) T[x].x=T[l].x,T[x].k=T[l].k,T[x].v=T[l].v; else if (T[l].k>T[r].k) T[x].x=T[r].x,T[x].k=T[r].k,T[x].v=T[r].v; else { if (T[l].v<=T[r].v) T[x].x=T[l].x,T[x].k=T[l].k,T[x].v=T[l].v; else if (T[l].v>T[r].v) T[x].x=T[r].x,T[x].k=T[r].k,T[x].v=T[r].v; } } inline void down(int x) { if (!T[x].lz) return; T[ls(x)].nk-=T[x].lz; T[rs(x)].nk-=T[x].lz; T[ls(x)].lz+=T[x].lz; T[rs(x)].lz+=T[x].lz; T[x].lz=0; } void build(int x,int l,int r) { if (l==r) { T[x].nx=T[x].x=l,T[x].v=V[p[l]],T[x].k=T[x].nk=K[p[l]]; return; } int mid(l+r>>1); build(ls(x),l,mid); build(rs(x),mid+1,r); up(x); } void updates(int x,int p,int l,int r) { if (l==r) return (void)(T[x].nk=INF,T[x].k=T[x].v=INF); int mid(l+r>>1); down(x); if (p<=mid) updates(ls(x),p,l,mid); else if (p>mid) updates(rs(x),p,mid+1,r); up(x); } void update(int x,int l,int r,int lt,int rt) { if (l<=lt&&rt<=r) return (void)(--T[x].nk,p(T[x].lz)); int mid(lt+rt>>1); down(x); if (l<=mid) update(ls(x),l,r,lt,mid); if (r>mid) update(rs(x),l,r,mid+1,rt); up(x); } }T; inline int main() { //FI=freopen("nanfeng.in","r",stdin); //FO=freopen("nanfeng.out","w",stdout); read(n); for (ri i(1);i<=n;p(i)) read(K[i]),read(V[i]),p[i]=i; sort(p+1,p+n+1,cmp); int lst=-1,nm=0; for (ri i(1);i<=n;p(i)) { int cur=p[i]; if (V[cur]==lst) ans*=cmin(i-1-nm,K[cur]-1)+nm+1,p(nm); else ans*=cmin(i-1,K[cur]-1)+1,nm=1; lst=V[cur]; ans%=MOD; } lst=n; for (ri i(n);i;--i) { int cur=p[i]; if (V[p[lst]]==V[cur]) pre[i]=lst; else pre[i]=lst=i; } printf("%lld\n",ans); T.build(1,1,n); for (ri i(1);i<=n;p(i)) { int px; if (T.T[1].nk>1) printf("%d %d\n",T.T[1].k,T.T[1].v),px=T.T[1].x; else printf("%d %d\n",K[p[T.T[1].nx]],V[p[T.T[1].nx]]),px=T.T[1].nx; T.updates(1,px,1,n); if (pre[px]<n) T.update(1,pre[px]+1,n,1,n); } return 0; } } int main() {return nanfeng::main();}
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 深入理解 Mybatis 分库分表执行原理
· 如何打造一个高并发系统?
· .NET Core GC压缩(compact_phase)底层原理浅谈
· 现代计算机视觉入门之:什么是图片特征编码
· .NET 9 new features-C#13新的锁类型和语义
· Sdcb Chats 技术博客:数据库 ID 选型的曲折之路 - 从 Guid 到自增 ID,再到
· 语音处理 开源项目 EchoSharp
· 《HelloGitHub》第 106 期
· Spring AI + Ollama 实现 deepseek-r1 的API服务和调用
· 使用 Dify + LLM 构建精确任务处理应用