USACO 2018 December Contest Platinum T2: Sort It Out

题目大意

FJ有 N(1≤N≤1e5 )头奶牛(分别用 1…N 编号)排成一行。FJ喜欢他的奶牛以升序排列,不幸的是现在她们的顺序被打乱了。在过去FJ曾经使用一些诸如“冒泡排序”的开创性的算法来使他的奶牛排好序,但今天他想偷个懒。取而代之,他会每次对着一头奶牛叫道“按顺序排好”。当一头奶牛被叫到的时候,她会确保自己在队伍中的顺序是正确的(从她的角度看来)。当有一头紧接在她右边的奶牛的编号比她小,她们就交换位置。然后,当有一头紧接在她左边的奶牛的编号比她大,她们就交换位置。这样这头奶牛就完成了“按顺序排好”,在这头奶牛看来左边的奶牛编号比她小,右边的奶牛编号比她大。

FJ想要选出这些奶牛的一个子集,然后遍历这个子集,依次对着每一头奶牛发号施令(按编号递增的顺序),重复这样直到所有N头奶牛排好顺序。例如,如果她选出了编号为 {2,4,5} 的奶牛的子集,那么他会喊叫奶牛2,然后是奶牛4,然后是奶牛5。如果 N 头奶牛此时仍未排好顺序他会再次对着这几头奶牛喊叫,如果有必要的话继续重复。

由于FJ不确定哪些奶牛比较专心,他想要使得这个子集最小。此外,他认为 K 是个幸运数字。请帮他求出满足重复喊叫可以使得所有奶牛排好顺序的最小子集之中字典序第 K 小的子集。

我们称 {1,…,N} 的一个子集 S 在字典序下小于子集 T ,当 S 的所有元素组成的序列(按升序排列)在字典序下小于 T 的所有元素组成的序列(按升序排列)。例如, {1,3,6} 在字典序下小于 {1,4,5} 。

题目分析

观察题目,考虑一直对某个集合里的元素一直发号施令会产生什么结果。显然易见,该集合里的所有元素都最终会被排到自己那个最“合适”的位置,而集合外部的元素顺序不会改变。

既然我们要让全部元素从小到大排列,我们要让 选中集合 外部的元素有序。

这样的话,我们必须先求出 “选中集合 外部的元素有序” 的个数。显然,这就是个LIS问题。

设置结构体 Fi? 表示以权值为 i 结尾的 LIS的长度和数量,则可以从权值在 从 1 ?~ i−1?间转移过来,用树状数组维护前缀最大值和数量即可O(n logn)时间内解决。

回到本题,我们可以先用类似的方法,求出以每个点开头的LIS的最长长度和数量。这需要我们倒过来DP,并用树状数组维护后缀和而非前缀和。

在求出这些以后,我们从前往后扫一遍,把每个元素按以它开头的LIS长度,放到n个vector里。(为什么是n个,因为可能序列本身就是有序,长度为n)

然后我们按长度推。对于每个长度,依次遍历这个vector(已经字典序从大到小了),如果当前位置i开头的LIS数量num(i)<k,则k-=num(i),否则我们要选的就是当前位。

注意选了位置i以后,小于i的位置都不能再选,需要把这些位置的LIS数量清零。

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 const ll Inf=1e18+10;
 5 const int MAXN=1e5+10;
 6
 7 ll k;
 8 int n;
 9 int a[MAXN];
10
11 struct Node{
12     int len;ll num;
13     Node(int len_=0,ll num_=0){len=len_;num=num_;}
14 }BIT[MAXN],f[MAXN];
15
16
17 inline void Work(Node &x,Node y){
18     if(x.len>y.len) return;
19     if(x.len<y.len) x=y;
20     else x.num=min(Inf,x.num+y.num);
21 }
22 inline int lowbit(int x){
23     return x&(-x);
24 }
25 inline void Update(int x,Node y){
26     for(int i=x;i;i-=lowbit(i))
27         Work(BIT[i],y);
28 }
29 inline Node Query(int x){
30     Node res=Node(0,1);
31     for(int i=x;i<=n;i+=lowbit(i))
32         Work(res,BIT[i]);
33     return res;
34 }
35 vector<int> v[MAXN];
36 bool used[MAXN];
37 int main(){
38     scanf("%d%lld",&n,&k);
39     for(int i=1;i<=n;++i)
40         scanf("%d",&a[i]);
41     for(int i=n;i>=1;--i){
42         f[i]=Query(a[i]+1);
43         f[i].len++;
44         Update(a[i],f[i]);
45     }
46     for(int i=1;i<=n;++i)
47         v[f[i].len].push_back(i);
48     for(int len=Query(1).len,r=1;len>=1;--len){
49         for(int i=0;i<(int)v[len].size();++i){
50             int tmp=v[len][i];
51             if(f[tmp].num<k) k-=f[tmp].num;
52             else{
53                 used[a[tmp]]=1;
54                 while(r<=tmp) f[r++].num=0;
55                 break;
56             }
57         }
58     }
59     printf("%d\n",n-Query(1).len);
60     for(int i=1;i<=n;++i)
61         if(!used[i])
62             printf("%d\n",i);
63     return 0;
64 }

原文地址:https://www.cnblogs.com/LI-dox/p/11217096.html

时间: 2024-10-09 22:12:19

USACO 2018 December Contest Platinum T2: Sort It Out的相关文章

USACO 2017 December Contest Platinum T2: Push a Box

题目大意 一个谷仓是一个N*M的矩形网格,有一些网格里有干草.Bessie站在其中一个格子内,还有一个格子里有一个大木箱.Bessie不能和大木箱在一个格子里,也不能和干草在一个格子里. 如果她不与干草一个格子,她就可以往自己旁边的四个方向(东西南北)移动,如果她想移动到有木箱的格子里,那个木箱就会被她推一格(只要木箱的那个方向还有空间),如果没有空间,那Bessie就不能移动了. 给你谷仓的布局(空格子,干草以及木箱位置)以及Bessie的出发位置和箱子要被推到的位置,请你帮忙计算Bessie

USACO 2017 December Contest Platinum T3: Greedy Gift Takers

题目大意 有 N(1≤N≤1e5)头牛按顺序排成一列,编号从 1 到 N,1 号牛在队头,N 号牛在队尾. 每次位于队头的牛 i 拿到一个礼物,然后插入到从队尾数ci?头牛之前的位置..举个栗子: 初始队列 1,2,3,4,5 c1?= 2,c2? = 3,则第一次操作后的序列为 2,3,1,4,5,第二次操作后的序列为 3,2,1,4,5.重复无限次操作,求最后有几头牛拿不到礼物. 题目分析 一上来有个显然的结论,若一个人得不到礼物那么原序列中在他后面的人肯定也得不到礼物,因为后面的人跳不到前

USACO 2007 December Contest, Silver Problem 2. Building Roads Kruskal最小生成树算法

PROBLEM: (ENGLISH VERSION) Farmer John had just acquired several new farms! He wants to connect the farms with roads so that he can travel from any farm to any other farm via a sequence of roads; roads already connect some of the farms. Each of the N

USACO 2016 December Contest Gold T1: Moocast

题目大意 FJ的N头牛(1≤N≤1000)为了在他们之间传播信息, 想要组织一个"哞哞广播"系统. 奶牛们决定去用步话机装备自己而不是在很远的距离之外互相哞哞叫, 所以每一头奶牛都必须有一个步话机. 这些步话机都有一个限制传播半径, 但是奶牛们可以间接地通过中间奶牛传播信息, 所以并不是每头牛都必须直接向其他每一头奶牛连边. 奶牛们需要去决定多少钱花在步话机上, 如果他们花了$X, 那么他们都将会得到sqrt(x)距离的步话机. 所以, 两头牛之间的欧几里得距离平方最多是X. 请帮助奶

USACO 2016 December Contest Gold T3: Lasers and Mirrors

题目大意 出于某种原因,农夫约翰的牛总是在举行激光表演. 对于他们的最新展会,奶牛已经购买了一个大功率的激光器 - 这么大,事实上,他们似乎不能轻易地从它交付的位置移动.他们想以某种方式将激光的光发送到FJ物业另一侧的谷仓.激光器和谷仓都可以被认为位于FJ农场的地图上的2D平面中的点上.牛计划指挥激光器,使得它发出水平或竖直(即,与x或y轴平行)的光束.他们会将这个光束从一些镜子反射回去,直接到谷仓. 在农场上有N个栅栏(1≤N≤100,000),位于不同的二维点(也不同于激光和谷仓),牛可以安

USACO 2017 December Contest Gold T1: A Pie for a Pie

题目大意 Bessie和Elsie各自烤了 N(1≤N≤10^5)个馅饼.Bessie 会这 2N 个馅饼打分,Elsie 也会.二者的打分均为一个 ≤1e9 的非负整数.由于她们口味不同,每个派的两个分数可能不同.她们想互赠礼物.开始时,Bessie 送给 Elsie 一个馅饼.她们收到礼物(对方做的馅饼)后都会回赠对方一个自己做的馅饼.她们选择回礼的方法相同.以 Elsie 为例,Elsie 根据自己的打分来选择回礼.回礼的分数至少要大于她收到的馅饼的分数,但两个馅饼的分数差不能大于 D(0

USACO 2015 February Contest Gold T2: Censoring

题目大意 FJ把杂志上所有的文章摘抄了下来并把它变成了一个长度不超过10^5的字符串S.他有一个包含n个单词的列表,列表里的n个单词记为t1...tN.他希望从S中删除这些单词. FJ每次在S中找到最早出现的列表中的单词(最早出现指该单词的开始位置最小),然后从S中删除这个单词.他重复这个操作直到S中没有列表里的单词为止.注意删除一个单词后可能会导致S中出现另一个列表中的单词 FJ注意到列表中的单词不会出现一个单词是另一个单词子串的情况,这意味着每个列表中的单词在S中出现的开始位置是互不相同的

USACO 2019 January Contest Platinum T3: Train Tracking 2

题目大意 每天特快列车都会经过农场.列车有N节车厢(1≤N≤10^5),每节车厢上有一个1到10^9之间的正整数编号:不同的车厢可能会有相同的编号. 平时,Bessie会观察驶过的列车,记录车厢的编号.但是今天雾实在太浓了,Bessie一个编号也看不见!幸运的是,她从城市里某个可靠的信息源获知了列车编号序列的所有滑动窗口中的最小值.具体地说,她得到了一个正整数K,以及N−K+1个正整数c1,…,cN+1−K,其中ci是车厢i,i+1,…,i+K−1之中编号的最小值. 帮助Bessie求出满足所有

USACO 2019 February Contest Platinum T1: Cow Dating

题目大意 由于目前可供奶牛们使用的约会网站并没有给Farmer John留下深刻印象,他决定推出一个基于新匹配算法的奶牛交友网站,该算法可基于公牛和母牛间的共同兴趣对公牛和母牛进行匹配. Bessie在寻找情人节Barn Dance的合作伙伴时,决定试用这个网站.在注册账户之后,FJ的算法为他给出了一个长度为 N(1≤N≤1e6) 的匹配列表,列表上每头公牛接受她舞蹈邀请的概率为 p (0 < p < 1). Bessie决定向列表中的一个连续区间内的奶牛发送邀请,但Bessie希望恰好只有一