[JZOJ6400]:Game(贪心+线段树+二分)
题目描述
小$A$和小$B$在玩一个游戏,他们两个人每人有$n$张牌,每张牌有一个点数,并且在接下来的$n$个回合中每回合他们两人会分别打出手中的一张牌,点数严格更高的一方得一分,然而现在小$A$通过某种神秘的方法得到了小$B$的出牌顺序,现在他希望规划自己的出牌顺序使得自己在得分尽可能高的前提下出牌的字典序尽可能大。
输入格式
第一行一个正整数$n$表示游戏进行的轮数。
接下来一行$n$个整数,第$i$个数表示第$i$轮小$B$将要打出的牌的点数。
接下来一行$n$个整数,表示小$A$拥有的牌的点数。
输出格式
输出一行$n$个整数,表示小$A$出牌的顺序。
样例
样例输入:
5
1 2 3 4 5
3 2 2 1 4
样例输出:
2 3 4 2 1
数据范围与提示
对于$20\%$的数据,$n\leqslant 10$
对于$40\%$的数据,$n\leqslant 3,000$
对于$60\%$的数据,$n\leqslant 6,000$
对于$100\%$的数据,$n,a_i\leqslant 100,000$
题解
考虑贪心,一定是尽量拿小的压他更优。
这个排个序解决即可。
考虑如何另字典序最大,试着反着考虑。
发现答案满足单调性,考虑二分。
用线段树维护最大得分,然后在每一位上二分,利用贪心找到能够满足答案的最大得分即可。
时间复杂度:$\Theta(n\log n)$。
期望得分:$100$分。
实际得分:$100$分。
代码时刻
#include<bits/stdc++.h>
#define L(x) x<<1
#define R(x) x<<1|1
using namespace std;
unordered_map<int,int>mp;
int n;
int a[100001],b[100001],lc[200001],top,cnt;
int trns[400001],trsz[400001][2],trrk[400001];
void pushup(int x)
{
int res=min(trsz[L(x)][0],trsz[R(x)][1]);
trns[x]=trns[L(x)]+trns[R(x)]+res;
trsz[x][0]=trsz[L(x)][0]+trsz[R(x)][0]-res;
trsz[x][1]=trsz[L(x)][1]+trsz[R(x)][1]-res;
trrk[x]=trrk[L(x)]+trrk[R(x)];
}
void add(int x,int l,int r,int k,int id,int w)
{
if(l==r)
{
trsz[x][id]+=w;
trrk[x]+=id*w;
return;
}
int mid=(l+r)>>1;
if(k<=mid)add(L(x),l,mid,k,id,w);
else add(R(x),mid+1,r,k,id,w);
pushup(x);
}
int ask(int x,int l,int r,int k)
{
if(l==r)return l;
int mid=(l+r)>>1;
if(k<=trrk[L(x)])return ask(L(x),l,mid,k);
else return ask(R(x),mid+1,r,k-trrk[L(x)]);
}
int get(int x,int l,int r,int k)
{
if(l==r)return trrk[x];
int mid=(l+r)>>1;
if(k<=mid)return get(L(x),l,mid,k);
else return get(R(x),mid+1,r,k)+trrk[L(x)];
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++){scanf("%d",&b[i]);lc[++top]=b[i];}
for(int i=1;i<=n;i++){scanf("%d",&a[i]);lc[++top]=a[i];}
sort(lc+1,lc+top+1);
for(int i=1;i<=top;i++)if(lc[i]!=lc[i-1])mp[lc[i]]=++cnt;
for(int i=1;i<=n;i++)
{
lc[mp[a[i]]]=a[i];
lc[mp[b[i]]]=b[i];
a[i]=mp[a[i]];
b[i]=mp[b[i]];
add(1,1,cnt,a[i],1,1);
add(1,1,cnt,b[i],0,1);
}
for(int i=1;i<=n;i++)
{
int res=trns[1];
int l=get(1,1,cnt,b[i])+1;
int r=trrk[1];
add(1,1,cnt,b[i],0,-1);
if(l<=r)
{
while(l<r)
{
int mid=(l+r+1)>>1;
int tmp=ask(1,1,cnt,mid);
add(1,1,cnt,tmp,1,-1);
if(trns[1]+1==res)l=mid;
else r=mid-1;
add(1,1,cnt,tmp,1,1);
}
int tmp=ask(1,1,cnt,l);
add(1,1,cnt,tmp,1,-1);
if(trns[1]+1==res)
{
printf("%d ",lc[tmp]);
continue;
}
add(1,1,cnt,tmp,1,1);
}
l=1,r=get(1,1,cnt,b[i]);
while(l<r)
{
int mid=(l+r+1)>>1;
int tmp=ask(1,1,cnt,mid);
add(1,1,cnt,tmp,1,-1);
if(trns[1]==res)l=mid;
else r=mid-1;
add(1,1,cnt,tmp,1,1);
}
int tmp=ask(1,1,cnt,l);
add(1,1,cnt,tmp,1,-1);
printf("%d ",lc[tmp]);
}
return 0;
}
rp++
[JZOJ6400]:Game(贪心+线段树+二分)的更多相关文章
- hdu 5338 ZZX and Permutations (贪心+线段树+二分)
ZZX and Permutations Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/O ...
- Codeforces Gym 100231B Intervals 线段树+二分+贪心
Intervals 题目连接: http://codeforces.com/gym/100231/attachments Description 给你n个区间,告诉你每个区间内都有ci个数 然后你需要 ...
- Codeforces Gym 100803G Flipping Parentheses 线段树+二分
Flipping Parentheses 题目连接: http://codeforces.com/gym/100803/attachments Description A string consist ...
- hdu4614 线段树+二分 插花
Alice is so popular that she can receive many flowers everyday. She has N vases numbered from 0 to N ...
- BZOJ4391 High Card Low Card [Usaco2015 dec](贪心+线段树/set库
正解:贪心+线段树/set库 解题报告: 算辣直接甩链接qwq 恩这题就贪心?从前往后从后往前各推一次然后找一遍哪个地方最大就欧克了,正确性很容易证明 (这里有个,很妙的想法,就是,从后往前推从前往后 ...
- 洛谷P4344 脑洞治疗仪 [SHOI2015] 线段树+二分答案/分块
!!!一道巨恶心的数据结构题,做完当场爆炸:) 首先,如果你用位运算的时候不小心<<打成>>了,你就可以像我一样陷入疯狂的死循环改半个小时 然后,如果你改出来之后忘记把陷入死循 ...
- luogu4422 [COCI2017-2018#1] Deda[线段树二分]
讨论帖:线段树二分的题..我还考场切过..白学 这题我一年前的模拟赛考场还切过,现在就不会了..好菜啊. 显然直接线段树拆成$\log n$个区间,然后每个区间在进行线段树二分即可. UPD:复杂度分 ...
- bzoj4399 魔法少女LJJ 线段树合并+线段树二分+并查集
题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=4399 题解 毒瘤题 \(9\) 种操作还有支持动态图的连通性 仔细读题 $ c<=7$. ...
- [BZOJ 2653] middle(可持久化线段树+二分答案)
[BZOJ 2653] middle(可持久化线段树+二分答案) 题面 一个长度为n的序列a,设其排过序之后为b,其中位数定义为b[n/2],其中a,b从0开始标号,除法取下整. 给你一个长度为n的序 ...
随机推荐
- redmine3.4.6安装教程
Redmine 是一个开源的.基于Web的项目管理和缺陷跟踪工具. 参考了网上各种文章,终于成功安装redmine-3.4.6. 1.下载安装railsinstaller-3.4.0.exe 官网下载 ...
- 剑指offer-正则表达式匹配-字符串-python****
# -*- coding:utf-8 -*- ''' 题目:请实现一个函数用来匹配包括'.'和'*'的正则表达式. 模式中的字符'.'表示任意一个字符(不包括空字符!),而'*'表示它前面的字符可以出 ...
- 错误:SyntaxError: identifier starts immediately after numeric literal
转载:http://blog.csdn.net/shalousun/article/details/39995443在用JavaScript时,当你使用一个字符传作为函数的参数常常会看到语法错误,在f ...
- WPF ListView多行显示
//前台 <ListView Margin="14,152,12,74" Name="lvList" SelectionMode="Multip ...
- Express multer 文件上传
npm multer 文件上传 Express app 范本就不写了,仅记录一下上传部分的代码. const fs = require('fs'); const express = require(' ...
- vue学习【一】vue引用封装echarts并展示多个echarts图表
大家好,我是一叶,经过一段时间对vue的学习,我打算把vue做一个系列,把踩过的坑和大家分享一下. 现在开始第一章:vue引用并封装echarts 在文章开始前,我先舔波echarts(真香).阿里的 ...
- TensorFlow入门——hello
上一节说了TensorFlow的安装,这一节说一下测试的问题 新建一个Python文件,输入 import tensorflow as tf hello = tf .constant (’Hello, ...
- h5图片展示和ajax上传
<img src="" id="img"/> <script src="http://static.lamian.tv//pc/pu ...
- elastic 查询
1.match 查询 GET /_index/_search { "query": { "match": { " } } } 1.match 多条件查 ...
- centos8 网卡命令(centos7也可用)
nmcli n 查看nmcli状态 nmcli n on 启动nmcli nmcli c up eth0 启动网卡eth0 nmcli c down eth0 关闭网卡eth0 nmcli d c ...