1364 最大字典序排列
基准时间限制:1 秒 空间限制:131072 KB 分值: 80 难度:5级算法题

给出一个1至N的排列,允许你做不超过K次操作,每次操作可以将相邻的两个数交换,问能够得到的字典序最大的排列是什么?

例如:N = 5, {1 2 3 4 5},k = 6,在6次交换后,能够得到的字典序最大的排列为{5 3 1 2 4}。
Input
第1行:2个数N, K中间用空格分隔(1 <= N <= 100000, 0 <= K <= 10^9)。
第2至N + 1行:每行一个数i(1 <= i <= N)。
Output
输出共N行,每行1个数,对应字典序最大的排列的元素。
Input示例
5 6
1
2
3
4
5
Output示例
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 最大字典序排列(线段树)的更多相关文章

  1. 51Node 1364--- 最大字典序排列(树状数组)

    51Node  1364--- 最大字典序排列(树状数组) 1364 最大字典序排列 基准时间限制:1 秒 空间限制:131072 KB 分值: 80 难度:5级算法题  收藏  关注 给出一个1至N ...

  2. 51nod 1463 找朋友(线段树+离线处理)

    http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1463 题意: 思路: 好题! 先对所有查询进行离线处理,按照右区间排序, ...

  3. 51nod 1494 选举拉票 | 线段树

    51nod1494 选举拉票 题面 现在你要竞选一个县的县长.你去对每一个选民进行了调查.你已经知道每一个人要选的人是谁,以及要花多少钱才能让这个人选你.现在你想要花最少的钱使得你当上县长.你当选的条 ...

  4. 51nod 1081 子段求和(线段树 | 树状数组 | 前缀和)

    题目链接:子段求和 题意:n个数字序列,m次询问,每次询问从第p个开始L长度序列的子段和为多少. 题解:线段树区间求和 | 树状数组区间求和 线段树: #include <cstdio> ...

  5. 51nod 1480 打广告(二分+线段树)

    题意 给出n个区间和m个区间,从这n个区间里选一个区间a,这m个区间选一个区间b,使得a&b的长度*c最大. 思路 如果这n个区间里有一个区间包含另一个区间,那另外一个区间就可以忽略掉,进行\ ...

  6. 51nod 1463 找朋友 (扫描线+线段树)

    1463 找朋友  基准时间限制:1.5 秒 空间限制:262144 KB 分值: 80 难度:5级算法题  收藏  关注 给定: 两个长度为n的数列A .B 一个有m个元素的集合K 询问Q次 每次询 ...

  7. 51nod 1494 选举拉票 (线段树+扫描线)

    1494 选举拉票  题目来源: CodeForces 基准时间限制:1 秒 空间限制:131072 KB 分值: 80 难度:5级算法题  收藏  关注 现在你要竞选一个县的县长.你去对每一个选民进 ...

  8. 51nod 1571 最近等对 | 线段树 离线

    51nod 1571 最近等对 题面 现在有一个序列 a1, a2, ..., an ,还有m个查询 lj, rj (1 ≤ lj ≤ rj ≤ n) .对于每一个查询,请找出距离最近的两个元素 ax ...

  9. 51nod 1208 窗上的星星 | 线段树 扫描线

    51nod 1208 Stars In Your Window 题面 整点上有N颗星星,每颗星星有一个亮度.用一个平行于x轴和y轴,宽为W高为H的方框去套星星.套住的所有星星的亮度之和为S(包括边框上 ...

随机推荐

  1. 关于from nltk.book import * 报错解决方法

    import nltk nltk.download() 在使用上面命令安装了nltk库并运行下载后,再输入from nltk.book import * 往往会出现这样的错误提示: 出现这种错误往往是 ...

  2. 一个C&C++程序的生命历程

    翻了好多博客,内容星星点点,没找到我想要的,现在吸取大神精华,加上本人拙见,总结如下: 一个C或C++程序从你开始编写,到结束,整个过程,都做了些什么,请看下文: 先看大体的过程:看图: 我在这里主要 ...

  3. CentOS 7 安装Graphite

    Graphite简介 Graphite是一个Python编写的企业级开源监控工具,采用django框架,用来收集服务器所有的即时状态,用户请求信息,Memcached命中率,RabbitMQ消息服务器 ...

  4. JAVA_SE基础——43.抽象类

    高手勿喷~ 抽象类:当定义一个类时,常常需要定义一些方法来描述该类的行为特征,但有时这些方法的实现方式是无法确定的.例如定义Animal类时,shout()方法用于表示动物的叫声,但是针对不同的动物, ...

  5. vmvare入门(1)使用移动,不要使用复制

    1.复制虚拟机会产生新的自动网卡,原来的 System Eth0废了? 2.xftp链接的时候,要选择sftp方式连接,utf8编码.

  6. Spring Security入门(2-2)Spring Security 的运行原理 2

  7. C# Bootstrap table之 分页

    效果如图: 一.声明talbe <div class="container"> <table id="table" class="t ...

  8. Opencv出现“_pFirstBlock == pHead”错误的解决方法

    先说结论: opencv链接库使用错误. 1,确认VS工程属性中,opencv的链接库路径和版本正确. VS2013应该使用vc12目录,VS2012对应vc11目录.debug版和release版要 ...

  9. jquery楼层效果

  10. Delphi 10.2.3 + Xcode 9.2 开发 IOS 程序,免证书+免越狱,真机调试

    工具列表: 1,delphi 10.2.3 + PAServer19.0. 2,配置好一些的 PC 一台,建议至少 4 代 intel i5 + 16G + 256GSSD,低于此配置将产生拖延症. ...