题目描述

  小$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(贪心+线段树+二分)的更多相关文章

  1. hdu 5338 ZZX and Permutations (贪心+线段树+二分)

    ZZX and Permutations Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/O ...

  2. Codeforces Gym 100231B Intervals 线段树+二分+贪心

    Intervals 题目连接: http://codeforces.com/gym/100231/attachments Description 给你n个区间,告诉你每个区间内都有ci个数 然后你需要 ...

  3. Codeforces Gym 100803G Flipping Parentheses 线段树+二分

    Flipping Parentheses 题目连接: http://codeforces.com/gym/100803/attachments Description A string consist ...

  4. hdu4614 线段树+二分 插花

    Alice is so popular that she can receive many flowers everyday. She has N vases numbered from 0 to N ...

  5. BZOJ4391 High Card Low Card [Usaco2015 dec](贪心+线段树/set库

    正解:贪心+线段树/set库 解题报告: 算辣直接甩链接qwq 恩这题就贪心?从前往后从后往前各推一次然后找一遍哪个地方最大就欧克了,正确性很容易证明 (这里有个,很妙的想法,就是,从后往前推从前往后 ...

  6. 洛谷P4344 脑洞治疗仪 [SHOI2015] 线段树+二分答案/分块

    !!!一道巨恶心的数据结构题,做完当场爆炸:) 首先,如果你用位运算的时候不小心<<打成>>了,你就可以像我一样陷入疯狂的死循环改半个小时 然后,如果你改出来之后忘记把陷入死循 ...

  7. luogu4422 [COCI2017-2018#1] Deda[线段树二分]

    讨论帖:线段树二分的题..我还考场切过..白学 这题我一年前的模拟赛考场还切过,现在就不会了..好菜啊. 显然直接线段树拆成$\log n$个区间,然后每个区间在进行线段树二分即可. UPD:复杂度分 ...

  8. bzoj4399 魔法少女LJJ 线段树合并+线段树二分+并查集

    题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=4399 题解 毒瘤题 \(9\) 种操作还有支持动态图的连通性 仔细读题 $ c<=7$. ...

  9. [BZOJ 2653] middle(可持久化线段树+二分答案)

    [BZOJ 2653] middle(可持久化线段树+二分答案) 题面 一个长度为n的序列a,设其排过序之后为b,其中位数定义为b[n/2],其中a,b从0开始标号,除法取下整. 给你一个长度为n的序 ...

随机推荐

  1. 基于Hadoop伪分布式集群搭建Spark

    一.前置安装 1)JDK 2)Hadoop伪分布式集群 二.Scala安装 1)解压Scala安装包 2)环境变量 SCALA_HOME = C:\ProgramData\scala-2.10.6 P ...

  2. go build命令详解

    原文地址讲解:https://blog.csdn.net/zl1zl2zl3/article/details/83374131

  3. 进程之multiprocessing模块代码篇

    这里再把之前的内容总结和补充一下: 并发和并行: 你在干坏事,来了一个电话,干完坏事再去接电话,说明你既不是并发也不是并行. 你在干坏事,来了一个电话,你接完电话接着干坏事,说明你支持并发 你在干坏事 ...

  4. luogu P3226 [HNOI2012]集合选数

    luogu 因为限制关系只和2和3有关,如果把数中2的因子和3的因子都除掉,那剩下的数不同的数是不会相互影响,所以每次考虑剩下的数一样的一类数,答案为每类数答案的乘积 如果选了一个数,那么2的因子多1 ...

  5. JS常见面试题总结-真实被问到的!

    1.判断数据类型有几种方法 console.log(typeof 'abc') // string console.log(Object.prototype.toString.call('abc')) ...

  6. LeetCode——回文链表

    题目 给定一个链表的头节点head,请判断该链表是否为回 文结构. 例如: 1->2->1,返回true. 1->2->2->1,返回true. 15->6-> ...

  7. Js 将图片的绝对路径转换为base64编码(3)

    图片文件改变一方法:$('#file').change(function(){var oFReader = new FileReader();oFReader.readAsDataURL(this.f ...

  8. Chrome OS 更新新版本可让Linux访问USB连接的Android设备

    谷歌再次为Chrome OS带来了重大版本更新,使版本号达到了75.本次更新的一大亮点就是允许在Chrome OS上运行的Linux能够识别通过USB方式连接的Android设备,能够让用户使用Lin ...

  9. Transformer, ELMo, GPT, 到Bert

    RNN:难以并行 CNN:filter只能考虑局部的信息,要叠多层 Self-attention:可以考虑全局的信息,并且可以并行 (Attention Is All You Need) 示意图:x1 ...

  10. server version for the right syntax to use near 'USING BTREE 数据库文件版本不合导致的错误

    MySQL 返回:#1064 - You have an error in your SQL syntax; check the manual that corresponds to your MyS ...