当前位置: 首页 > news >正文

决斗(模拟赛题目T3)分析

题目概述

田忌赛马的最大字典序。

分析

感觉很典,所以就记下来了。

我们考虑一个非常重要的事实:

  • 田忌赛马对于每一个 \(a_i\) 找的是第一个比他大的 \(b_i\)
  • 而字典序最大又需要前面的尽可能大。

这似乎产生了矛盾,让这道题目看起来有点难。

我们考虑不用 multiset 或者双指针求这个值,我们考虑分治的过程。

CDQ 分治是这样的:

对于左区间算好其分内的答案,右区间算好其分内的答案。

要合并区间的时候,左区间和右区间匹配就行了。

那么我们只需要记录每个区间剩下多少个 \(a\) 中的元素和 \(b\) 中的元素还没有匹配即可。

最精华的部分来了:由于我们对于每一个 \(a_i\) 肯定进行二分答案是否可行,因为字典序本质上就有一个贪心的过程。我们考虑把这个思想搬到一个可支持修改的线段树上面即可。

在线段树上面这个是好维护的,于是这道题就做完了。

代码

时间复杂度 \(\mathcal{O}(n\log V\log n)\)

#include <iostream>
#include <cstdio>
#include <cstring>
#include <stdlib.h>
#include <algorithm>
#include <vector>
#include <set>
#define int long long
#define N 100005
using namespace std;
struct node{int val,a,b;
}tr[N << 2];
#define ls(x) (x << 1)
#define rs(x) (x << 1 | 1)
void pushup(int x) {int res = min(tr[ls(x)].a,tr[rs(x)].b);tr[x].a = tr[ls(x)].a + tr[rs(x)].a - res;tr[x].b = tr[ls(x)].b + tr[rs(x)].b - res;tr[x].val = tr[ls(x)].val + tr[rs(x)].val + res;
}
void update(int x,int l,int r,int pos,int a,int b) {if (l == r) {tr[x].a += a,tr[x].b += b;return;}int mid = l + r >> 1;if (pos <= mid) update(ls(x),l,mid,pos,a,b);else update(rs(x),mid + 1,r,pos,a,b);pushup(x);
}
int n,a[N],b[N];
multiset<int> st;
signed main(){cin >> n;for (int i = 1;i <= n;i ++) scanf("%lld",&a[i]);for (int i = 1;i <= n;i ++) scanf("%lld",&b[i]);int m = 1e5;for (int i = 1;i <= n;i ++) {st.insert(b[i]);update(1,1,m,a[i],1,0);update(1,1,m,b[i],0,1);}int mx = tr[1].val;for (int i = 1;i <= n;i ++) {update(1,1,m,a[i],-1,0);int l = a[i] + 1,r = *st.rbegin(),res = -1;while(l <= r) {int mid = l + r >> 1;auto t = st.lower_bound(mid);if (t == st.end()) {r = mid - 1;continue;}update(1,1,m,*t,0,-1);if (tr[1].val + (a[i] < *t) == mx) l = mid + 1,res = *t;else r = mid - 1;update(1,1,m,*t,0,1);}if (res != -1) {st.erase(st.find(res));update(1,1,m,res,0,-1);printf("%lld ",res);mx --;continue;}l = *st.begin(),r = a[i],res = l;while(l <= r) {int mid = l + r >> 1;auto t = st.lower_bound(mid);if (t == st.end()) {r = mid - 1;continue;}update(1,1,m,*t,0,-1);if (tr[1].val == mx) l = mid + 1,res = *t;else r = mid - 1;update(1,1,m,*t,0,1);}update(1,1,m,res,0,-1);printf("%lld ",res);st.erase(st.find(res));}return 0;
}
http://www.jsqmd.com/news/10842/

相关文章:

  • Guidde:AI驱动的视频文档创建工具 - 详解
  • gitlen中,已经提交了内容,如何回退到修改前?
  • HCIP-IoT/H52-111 真题详解(章节C),接入实用的技术和网络设计 /Part1
  • CF1989F
  • 基于UML/MARTE的汽车安全关键系统设计手段
  • Vue3水波纹指令:2025年Material Design交互新标准 - 实践
  • Beyond Compare5最新破解版下载及安装使用教程
  • Why cant developing countries become developed?
  • 22 LCA模拟赛2T1 奶龙与贝利亚 题解
  • AI风险管控新规应对系统抵抗关闭行为
  • 01-Vue3阶段必会的前置知识-01变量和常量
  • 这是我的第一个个人博客
  • BLDC中的Q15
  • 251009
  • MaxProduct
  • 雪落 - L
  • PluginMonitor - Typecho 插件监控工具
  • STM32 教程
  • LibreChat-图文并茂手把手教你搭建自己的AI机器人 Step-by-step guide to building your own chatbot
  • Ignite3 竟然变成分布式数据库了!
  • NUIST 《程序设计基础》 实验1
  • [MIT 6.828] Lab 1 C, Assembly, Tools, and Bootstrapping
  • WCH低功耗蓝牙系列芯片usb烧录故障排查
  • 使用docker构建.net api镜像及nginx反向代理 - binzi
  • 利用sprintf与snprintf巧妙实现数值变量转换为字符串型
  • Helmholtz-Gibbs自由能与熵弹性
  • 日志|电话号码的字母组合|子集|回溯
  • Docker实用篇(初识Docker,Docker的基本操作,Dockerfile自定义镜像,Docker-Compose,Docker镜像仓库) - a
  • ROIR 2023
  • 【题解】P12992 [GCJ 2022 #1C] Intranets