题解 Game
一有「字典序最大」什么的的就懵了……这题我颓的std
首先可以发现全局最大得分很好统计,我们令它为 \(k\)
然后我们尝试构造方案,但发现无论怎么放都可能会有后效性
发现对于一个位置,可以放在这里的数有单调性
也即如果有一个比较大的数放在了这里,后面可能就匹配不够 \(k\) 个了
所以我们可以check一下, 对每个位置分两种情况
我们找一个 \(a\) 与 \(b[i]\) 形成匹配:
那这时我们二分一个 \(a\) ,check一下去掉这个 \(a\) 后后面还能不能形成 \(k-1\) 个匹配
如果check最后二分出的结果也不能满足,说明这个地方就不能匹配我们找一个 \(a\) ,但它无法与 \(b[i]\) 形成匹配:
二分一个最大的 \(a\) ,且删掉这个 \(a\) 后后面仍能形成 \(k\) 个匹配
然后就是如何check了……可以 \(O(n)\) 跑check
神仙思路:开一棵权值线段树,分别维护这段值域中剩余未匹配a, b的个数及匹配的数量
因为右区间的a一定可以匹配左区间的b,所以这个东西可以合并
然后就每次单点修改删掉一个数,看根节点的匹配个数就行了
- 处理「字典序最大/小的合法方案」(?):如果每个位置的取值有单调性,二分找这里能放的,且这里放了后面仍能满足要求的最大的取值。其实这样的话难点在于check
Code:
#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define N 100010
#define ll long long
//#define int long long
char buf[1<<21], *p1=buf, *p2=buf;
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf, 1, 1<<21, stdin)), p1==p2?EOF:*p1++)
inline int read() {
int ans=0, f=1; char c=getchar();
while (!isdigit(c)) {if (c=='-') f=-f; c=getchar();}
while (isdigit(c)) {ans=(ans<<3)+(ans<<1)+(c^48); c=getchar();}
return ans*f;
}
int n;
int a[N], b[N];
namespace force{
int ans[N], maxn;
void solve() {
sort(a+1, a+n+1);
do {
int cnt=0;
for (int i=1; i<=n; ++i) if (a[i]>b[i]) ++cnt;
if (cnt>=maxn) memcpy(ans+1, a+1, sizeof(int)*n), maxn=cnt;
} while (next_permutation(a+1, a+n+1));
for (int i=1; i<=n; ++i) printf("%d ", ans[i]);
printf("\n");
exit(0);
}
}
namespace task1{
int a2[N], b2[N], ans[N];
int cnt[N];
inline bool cmp(int a, int b) {return a>b;}
bool check(int k) {
int pos=1;
for (int i=1; i<=k; ++i) {
for (; pos<=n; ++pos) {
if (a2[i]>b2[pos]) {
++pos;
goto jump;
}
}
if (pos>n) return 0;
jump: ;
}
return 1;
}
void solve() {
for (int i=1; i<=n; ++i) ++cnt[a[i]];
memcpy(a2, a, sizeof(a));
memcpy(b2, b, sizeof(b));
sort(a2+1, a2+n+1, cmp); sort(b2+1, b2+n+1, cmp);
int l=0, r=n, mid;
while (l<=r) {
mid=(l+r)>>1;
if (check(mid)) l=mid+1;
else r=mid-1;
}
mid=l-1;
//cout<<"mid: "<<mid<<endl;
for (int i=1; i<=mid; ++i) --cnt[a2[i]];
int pos=1;
for (int i=1; i<=mid; ++i) {
for (; pos<=n; ++pos) {
if (a2[i]>b2[pos]) {
ans[pos]=a2[i];
++pos;
goto jump2;
}
}
jump2: ;
}
pos=1;
for (int i=N; ~i; --i)
while (cnt[i]) {
while (ans[pos]) ++pos;
ans[pos]=i;
--cnt[i];
}
for (int i=1; i<=n; ++i) printf("%d ", ans[i]);
printf("\n");
exit(0);
}
}
namespace task{
multiset<int> s;
int tl[N<<2], tr[N<<2], sa[N<<2], sb[N<<2], sum[N<<2], k;
#define tl(p) tl[p]
#define tr(p) tr[p]
#define sa(p) sa[p]
#define sb(p) sb[p]
#define sum(p) sum[p]
void pushup(int p) {
//cout<<"pushup "<<p<<' '<<tl(p)<<' '<<tr(p)<<endl;
//cout<<"sa: "<<sa(p<<1)<<' '<<sa(p<<1|1)<<endl;
//cout<<"sb: "<<sb(p<<1)<<' '<<sb(p<<1|1)<<endl;
int dlt=min(sb(p<<1), sa(p<<1|1));
sum(p)=sum(p<<1)+sum(p<<1|1)+dlt;
sa(p)=sa(p<<1)+sa(p<<1|1)-dlt;
sb(p)=sb(p<<1)+sb(p<<1|1)-dlt;
}
void build(int p, int l, int r) {
tl(p)=l; tr(p)=r;
if (l==r) return ;
int mid=(l+r)>>1;
build(p<<1, l, mid);
build(p<<1|1, mid+1, r);
}
void upd(int p, int pos, int dat, int typ) {
if (tl(p)==tr(p)) {(typ?sa:sb)[p]+=dat; return ;}
int mid=(tl(p)+tr(p))>>1;
if (pos<=mid) upd(p<<1, pos, dat, typ);
else upd(p<<1|1, pos, dat, typ);
pushup(p);
}
void query(int p) {
cout<<"query "<<p<<' '<<tl(p)<<' '<<tr(p)<<' '<<sa(p)<<' '<<sb(p)<<' '<<sum(p)<<endl;
if (tl(p)==tr(p)) return ;
query(p<<1); query(p<<1|1);
}
void solve() {
build(1, 1, N);
for (int i=1; i<=n; ++i) upd(1, a[i], 1, 1), s.insert(a[i]);
for (int i=1; i<=n; ++i) upd(1, b[i], 1, 0);
k=sum(1);
//query(1);
//cout<<"k: "<<k<<endl;
for (int i=1,l,r,mid,rb; i<=n; ++i) {
upd(1, b[i], -1, 0);
l=b[i]+1, r=rb=*s.rbegin();
//cout<<"lr: "<<l<<' '<<r<<endl;
while (l<=r) {
mid=(l+r)>>1;
upd(1, mid, -1, 1);
if (sum(1)==k-1) l=mid+1;
else r=mid-1;
upd(1, mid, 1, 1);
}
if (b[i]+1<=rb) upd(1, l-1, -1, 1);
if (b[i]+1<=rb && sum(1)==k-1) {--k; printf("%d ", l-1); s.erase(s.find(l-1));}
else {
if (b[i]+1<=rb) upd(1, l-1, 1, 1);
l=1, r=b[i];
while (l<=r) {
mid=(l+r)>>1;
upd(1, mid, -1, 1);
if (sum(1)==k) l=mid+1;
else r=mid-1;
upd(1, mid, 1, 1);
}
upd(1, l-1, -1, 1);
printf("%d ", l-1);
//if (s.find(l-1)==s.end()) cout<<"error2"<<endl;
s.erase(s.find(l-1));
}
}
printf("\n");
exit(0);
}
}
signed main()
{
n=read();
for (int i=1; i<=n; ++i) b[i]=read();
for (int i=1; i<=n; ++i) a[i]=read();
//force::solve();
//task1::solve();
task::solve();
return 0;
}
题解 Game的更多相关文章
- 2016 华南师大ACM校赛 SCNUCPC 非官方题解
我要举报本次校赛出题人的消极出题!!! 官方题解请戳:http://3.scnuacm2015.sinaapp.com/?p=89(其实就是一堆代码没有题解) A. 树链剖分数据结构板题 题目大意:我 ...
- noip2016十连测题解
以下代码为了阅读方便,省去以下头文件: #include <iostream> #include <stdio.h> #include <math.h> #incl ...
- BZOJ-2561-最小生成树 题解(最小割)
2561: 最小生成树(题解) Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 1628 Solved: 786 传送门:http://www.lyd ...
- Codeforces Round #353 (Div. 2) ABCDE 题解 python
Problems # Name A Infinite Sequence standard input/output 1 s, 256 MB x3509 B Restoring P ...
- 哈尔滨理工大学ACM全国邀请赛(网络同步赛)题解
题目链接 提交连接:http://acm-software.hrbust.edu.cn/problemset.php?page=5 1470-1482 只做出来四道比较水的题目,还需要加强中等题的训练 ...
- 2016ACM青岛区域赛题解
A.Relic Discovery_hdu5982 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Jav ...
- poj1399 hoj1037 Direct Visibility 题解 (宽搜)
http://poj.org/problem?id=1399 http://acm.hit.edu.cn/hoj/problem/view?id=1037 题意: 在一个最多200*200的minec ...
- 网络流n题 题解
学会了网络流,就经常闲的没事儿刷网络流--于是乎来一发题解. 1. COGS2093 花园的守护之神 题意:给定一个带权无向图,问至少删除多少条边才能使得s-t最短路的长度变长. 用Dijkstra或 ...
- CF100965C题解..
求方程 \[ \begin{array}\\ \sum_{i=1}^n x_i & \equiv & a_1 \pmod{p} \\ \sum_{i=1}^n x_i^2 & ...
- JSOI2016R3 瞎BB题解
题意请看absi大爷的blog http://absi2011.is-programmer.com/posts/200920.html http://absi2011.is-programmer.co ...
随机推荐
- Android控件总结
最常用的控件:TextView.EditText.Button.ImageView TextView 文本 ...
- MYSQL_Join注入技巧
Join注入技巧 join无名列报错注入 约束条件 在知到表名的前提下才能操作 注入语句 and extractvalue(1,concat(0x7e,(select * from (select * ...
- Vmware 恢复flat.vmdk和delta.vmdk
背景: 一次客户现场突然掉电,导致虚拟机文件夹里面的文件丢失,只剩余-flat.vmdk和-delta.vmdk文件,其他文件全部丢失,文件格式原本为"文件"格式.新建虚拟机无法直 ...
- python twain 扫描
def multiScan(self): """ Scan and return an array of PIL objects If no images, will r ...
- 10分钟系列:NetCore3.1+EFCore三步快速完成数据库交互
前言 做程序开发,不管是什么语言什么数据库,其中的ORM(对象关系映射)是必不可少的,但是不管选择哪一种ORM,都需要了解其中的运行机制,配置帮助类等等. 所以很多ORM都开始进行升级封装,我们只需要 ...
- 微信小程序云开发-云存储的应用-识别通用印刷体
一.准备工作 1.创建云函数identify 2.云函数identify中index.js代码 1 // 云函数入口文件 2 const cloud = require('wx-server-sdk' ...
- 技术期刊 · 天光台高未百尺 | Uber 工程师的 JS 算法课;大数据时代的个人隐私;设计师的 Github;告别 PPT 工程师;从零开始实现的像素画
蒲公英 · JELLY技术期刊 Vol.42 这是一个最好的时代,多样化的平台给了所有人成长发展的机会,各种需求和解决需求的人让人大开眼界:但这也并不是完美的时代,"前端还需要懂什么算法?& ...
- 用activiti实现类似钉钉审批流程-附整个系统源码
前言 目前市场上有很多开源平台没有整合工作流,即使有,也是价格不菲的商业版,来看这篇文章的估计也了解了行情,肯定不便宜.我这个快速开发平台在系统基础功能(用户管理,部门管理-)上整合了工作流,你可以直 ...
- JS对DOM的操作优化法则
html页面显示过程 解析HTML,并生成一棵DOM tree 解析各种样式并结合DOM tree生成一棵Render tree 对Render tree的各个节点计算布局信息,比如box的位置与尺寸 ...
- Linux系统进入redis并查询值
1.进入redisredis-cli -h ip -p port2.查看具体信息info 3.得到redis中存储的所有key值KEYS *4.获取指定key值的value值get "key ...