51nod 1364 最大字典序排列(线段树)
1364 最大字典序排列
基准时间限制:1 秒 空间限制:131072 KB 分值: 80 难度:5级算法题
第1行:2个数N, K中间用空格分隔(1 <= N <= 100000, 0 <= K <= 10^9)。
第2至N + 1行:每行一个数i(1 <= i <= N)。
输出共N行,每行1个数,对应字典序最大的排列的元素。
5 6
1
2
3
4
5
5
3
1
2
4
/*
51nod 1364 最大字典序排列(线段树) problem:
给出一个1至N的排列,允许你做不超过K次操作,每次操作可以将相邻的两个数交换,问能够得到的字典序最大的排列是什么?
例如:N = 5, {1 2 3 4 5},k = 6,在6次交换后,能够得到的字典序最大的排列为{5 3 1 2 4}。 solve:
贪心的思想. 从1~n维护第i个数尽可能大. 就成了在[i+1,k+i]中查找最大值. 然后把找到的数从后面的数组中删除插到前面.
因为我的删除是用num来表示,所以每次都要先找到对应区间的边界位置. 然后在计算移动过去需要多少步. 直到操作结束 hhh-2016/09/04-11:16:36
*/
#pragma comment(linker,"/STACK:124000000,124000000")
#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <vector>
#include <math.h>
#include <queue>
#include <set>
#include <map>
#define lson i<<1
#define rson i<<1|1
#define ll long long
#define clr(a,b) memset(a,b,sizeof(a))
#define scanfi(a) scanf("%d",&a)
#define scanfs(a) scanf("%s",a)
#define scanfl(a) scanf("%I64d",&a)
#define scanfd(a) scanf("%lf",&a)
#define key_val ch[ch[root][1]][0]
#define eps 1e-7
#define inf 0x3f3f3f3f3f3f3f3f
using namespace std;
const ll mod = 1000000007;
const int maxn = 100010;
const double PI = acos(-1.0);
int n;
int a[maxn];
struct node
{
int l,r,mid;
int pos,num;
int Max;
} tree[maxn<<2]; void push_up(int i)
{
if(tree[lson].Max >= tree[rson].Max)
{
tree[i].Max= tree[lson].Max;
tree[i].pos = tree[lson].pos;
}
else
{
tree[i].Max = tree[rson].Max;
tree[i].pos = tree[rson].pos;
}
tree[i].num = tree[lson].num + tree[rson].num;
} void build(int i,int l,int r)
{
tree[i].l = l,tree[i].r = r;
tree[i].mid = (l+r) >>1;
tree[i].num = 0;
if(l == r && l)
{
tree[i].num = 1;
tree[i].Max= a[l];
tree[i].pos = l;
return ;
}
build(lson,l,tree[i].mid);
build(rson,tree[i].mid+1,r);
push_up(i);
}
int tMax,tpos; void update(int i,int k)
{
if(tree[i].l >= k && tree[i].r <= k)
{
tree[i].Max = 0;
tree[i].num = 0;
return ;
}
int mid = tree[i].mid;
if(k <= mid)
update(lson,k);
else
update(rson,k);
push_up(i);
return ;
}
void query(int i,int l,int r)
{
if(tree[i].l >= l && tree[i].r <= r)
{
if(tMax < tree[i].Max)
tMax = tree[i].Max,tpos = tree[i].pos;
else if(tMax == tree[i].Max)
tpos = min(tree[i].pos,tpos);
return ;
}
int mid = tree[i].mid;
if(l <= mid)
query(lson,l,r);
if(r > mid)
query(rson,l,r);
push_up(i);
return ;
} int query_x(int i,int k)
{
if(tree[i].l == tree[i].r)
{
return tree[i].l;
}
int mid = tree[i].mid;
if(tree[lson].num >= k)
return query_x(lson,k);
else
return query_x(rson,k-tree[lson].num);
push_up(i);
} int query_num(int i,int l,int r)
{
if(tree[i].l >= l && tree[i].r <= r)
{
return tree[i].num;
}
int ans = 0;
if(l <=tree[i].mid)
ans += query_num(lson,l,r);
if(r > tree[i].mid)
ans += query_num(rson,l,r);
return ans;
} int ans[maxn];
int main()
{
int t;
// freopen("in.txt","r",stdin);
while(scanfi(n) != EOF)
{
scanfi(t);
a[0] = 0;
for(int i = 1; i <= n; i++)
{
scanfi(a[i]);
}
build(1,1,n);
int cnt = 1;
while(t > 0 && cnt <= n)
{
tMax = 0,tpos = n;
if(cnt + t >= n)
{
query(1,1,n);
update(1,tpos);
t -= query_num(1,1,tpos); printf("%d\n",tMax);
cnt++;
a[tpos] = -1;
}
else
{
int pos = query_x(1,t+1);
query(1,1,pos);
update(1,tpos);
t -= query_num(1,1,tpos);
cnt++;
printf("%d\n",tMax);
a[tpos] = -1;
}
}
for(int i = 1; i <= n; i++)
if(a[i] != -1)
printf("%d\n",a[i]);
}
return 0;
}
51nod 1364 最大字典序排列(线段树)的更多相关文章
- 51Node 1364--- 最大字典序排列(树状数组)
51Node 1364--- 最大字典序排列(树状数组) 1364 最大字典序排列 基准时间限制:1 秒 空间限制:131072 KB 分值: 80 难度:5级算法题 收藏 关注 给出一个1至N ...
- 51nod 1463 找朋友(线段树+离线处理)
http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1463 题意: 思路: 好题! 先对所有查询进行离线处理,按照右区间排序, ...
- 51nod 1494 选举拉票 | 线段树
51nod1494 选举拉票 题面 现在你要竞选一个县的县长.你去对每一个选民进行了调查.你已经知道每一个人要选的人是谁,以及要花多少钱才能让这个人选你.现在你想要花最少的钱使得你当上县长.你当选的条 ...
- 51nod 1081 子段求和(线段树 | 树状数组 | 前缀和)
题目链接:子段求和 题意:n个数字序列,m次询问,每次询问从第p个开始L长度序列的子段和为多少. 题解:线段树区间求和 | 树状数组区间求和 线段树: #include <cstdio> ...
- 51nod 1480 打广告(二分+线段树)
题意 给出n个区间和m个区间,从这n个区间里选一个区间a,这m个区间选一个区间b,使得a&b的长度*c最大. 思路 如果这n个区间里有一个区间包含另一个区间,那另外一个区间就可以忽略掉,进行\ ...
- 51nod 1463 找朋友 (扫描线+线段树)
1463 找朋友 基准时间限制:1.5 秒 空间限制:262144 KB 分值: 80 难度:5级算法题 收藏 关注 给定: 两个长度为n的数列A .B 一个有m个元素的集合K 询问Q次 每次询 ...
- 51nod 1494 选举拉票 (线段树+扫描线)
1494 选举拉票 题目来源: CodeForces 基准时间限制:1 秒 空间限制:131072 KB 分值: 80 难度:5级算法题 收藏 关注 现在你要竞选一个县的县长.你去对每一个选民进 ...
- 51nod 1571 最近等对 | 线段树 离线
51nod 1571 最近等对 题面 现在有一个序列 a1, a2, ..., an ,还有m个查询 lj, rj (1 ≤ lj ≤ rj ≤ n) .对于每一个查询,请找出距离最近的两个元素 ax ...
- 51nod 1208 窗上的星星 | 线段树 扫描线
51nod 1208 Stars In Your Window 题面 整点上有N颗星星,每颗星星有一个亮度.用一个平行于x轴和y轴,宽为W高为H的方框去套星星.套住的所有星星的亮度之和为S(包括边框上 ...
随机推荐
- bug终结者 团队作业第四、五周
bug终结者 团队作业第四.五周 博客编辑者:20162322朱娅霖 本周学习任务: 团队协作完成<需求规格说明书> 工作流程 第四周 团队成员各自完成蓝墨云班课中<需求规格说明书& ...
- 第201621123043 《Java程序设计》第12周学习总结
1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结多流与文件相关内容. 2. 面向系统综合设计-图书馆管理系统或购物车 使用流与文件改造你的图书馆管理系统或购物车. 2.1 简述如何 ...
- io多路复用(一)
sever端 1 import socket sk1 = socket.socket() sk1.bind(('127.0.0.1',8001,)) sk1.listen() sk2 = socket ...
- 技术文档分享_linux中生成考核用的GPT分区表结构修复
注:历史版本,后期改用python实现了 实验一: 目的:用于生成大量模拟破坏GPT分区结构案例,并生成唯一方式修复后的评判方法.故障:在一个完整的GPT分区磁盘上,丢失了GPT主分区表,或备份分区表 ...
- javascript原型链__proto__属性的理解
在javascript中,按照惯例,构造函数始终都应该以一个大写字母开头,而非构造函数则应该以一个小写字母开头.一个方法使用new操作符创建,例如下面代码块中的Person1(可以吧Person1看做 ...
- LeetCode & Q283-Move Zeroes-Easy
Array Two Pointers Description: Given an array nums, write a function to move all 0's to the end of ...
- Python内置函数(13)——bytearray
英文文档: class bytearray([source[, encoding[, errors]]]) Return a new array of bytes. The bytearray cla ...
- 链家2018春招Java工程师编程题题解
Light 题目描述 在小红家里面,有n组开关,触摸每个开关,可以使得一组灯泡点亮.现在问你,使用这n组开关,最多能够使得多少个灯泡点亮呢? 输入 第一行一个n,表示有n组开关.接下来n行,每行第一个 ...
- api-gateway实践(16)【租户模块:修改api定义】通过mq通知【开发者模块:更新开发者集市】
一.订阅关系 二.接收消息 dev模块接收更新本地集市
- maven常见问题处理(3-1)修改maven 默认使用的 jdk 版本
Eclipse工程应设定了1.8,maven编译仍然使用1.6的解决办法 解决方式有两种,一种是配置 pom.xml,一种是配置 settings.xml. 方式一:settings.xml 配置 打 ...