题目描述

我们说一个可重集 AA 比可重集 BB 小,当且仅当对于两个可重集中出现次数不同的最小元素 xx ,元素 xx 在 AA 中出现次数更多。

例如,可重集 {1,2,3}1,2,3 就比可重集 {1,3,3,5}1,3,3,5 小,类似的,{1,1,4,4}1,1,4,4 小于 {1,1,4}1,1,4 。

小 CC 给你了一个长度为 nn 的正整数序列 SS 。考虑 SS 的所有连续子序列,可以把它们分别看做一个可重集(也就是说,恰好存在着 \frac{n(n+1)}{2}2n(n+1)​ 个可重集)。

小 CC 想知道第 kk 小可重集,想请你帮她找到答案。

输入格式

输入共两行 。

第一行包含两个整数 n,kn,k 。

接下来的一行包含序列 S_iSi​ 。

输出格式

输出共一行。

输出你找到的可重集,请输出可重集排序后的结果。

可以用类似整体二分的缩小答案集合的思想,对于每个数确定在答案中应该出现几次。使用set来存答案的集合。

  1 #include <bits/stdc++.h>
2 #define N 100005
3 //#define loveGsy
4 using namespace std;
5 int n, k, s[N], hv[N], ans[N];
6 vector<int> pos[N];//存一个数出现在哪些位置
7 struct node {
8 int ll, lr, rl, rr;
9 node() {}
10 node(int a, int b, int c, int d) {ll = a, lr = b, rl = c, rr = d;}
11 friend bool operator < (node a, node b) {
12 return a.ll < b.ll;
13 }
14 };
15 set<node> st, hc;
16
17 int query(int p, int num) {
18 int l = 1, r = l + num - 1, js = 0, ll, lr, rl, rr, LL, LR, RL, RR;
19 set<node>::iterator zz;
20 while (r + 1 < pos[p].size()) {
21 LL = pos[p][l - 1] + 1;
22 LR = pos[p][l];
23 RL = pos[p][r];
24 RR = pos[p][r + 1] - 1;
25 zz = st.upper_bound(node(LR, 0, 0, 0));
26 while (zz != st.begin()) {
27 --zz;
28 if ((*zz).lr < LL) break;
29 ll = max((*zz).ll, LL);
30 lr = min((*zz).lr, LR);
31 rl = max((*zz).rl, RL);
32 rr = min((*zz).rr, RR);
33 if (lr >= ll && rr >= rl)
34 js += (lr - ll + 1) * (rr - rl + 1);
35 }
36 ++l, ++r;
37 }
38 return js;
39 }
40
41 void getnum(int p) {
42 ans[p] = hv[p];
43 while (ans[p]) {
44 int hc = query(p, ans[p]);//查询st集合内有多少区间满足有ans[p]个p
45 if (hc >= k) return ;
46 --ans[p];
47 k -= hc;//类似整体二分板题的答案分拆,缩小答案集合
48 }
49 }
50
51 void merge(int p, int num) {
52 int l = 1, r = l + num - 1, js = 0, ll, lr, rl, rr, LL, LR, RL, RR;
53 set<node>::iterator zz;
54 while (r + 1 < pos[p].size()) {
55 LL = pos[p][l-1] + 1;
56 LR = pos[p][l];
57 RL = pos[p][r];
58 RR = pos[p][r + 1] - 1;
59 zz = st.upper_bound(node(LR, 0, 0, 0));
60 while (zz != st.begin()) {
61 --zz;
62 if((*zz).lr < LL) break;
63 ll = max((*zz).ll, LL);
64 lr = min((*zz).lr, LR);
65 rl = max((*zz).rl, RL);
66 rr = min((*zz).rr, RR);//取交集
67 if(lr >= ll && rr >= rl)
68 hc.insert(node(ll,lr,rl,rr));
69 }
70 ++l,++r;
71 }
72 st.clear();//清空原来的集合
73 zz = hc.begin();
74 while (zz != hc.end()) {
75 st.insert((*zz));
76 ++zz;
77 }
78 hc.clear();
79 }
80
81 int main() {
82 #ifdef loveGsy
83 freopen("tree.in", "r", stdin);
84 freopen("tree.out", "w", stdout);
85 #endif
86 scanf("%d %d", &n, &k);
87 for (int i = 1; i <= n; i++) pos[i].push_back(0);//存边界条件
88 for (int i = 1; i <= n; i++) {
89 scanf("%d", &s[i]);
90 ++hv[s[i]];
91 pos[s[i]].push_back(i);
92 }
93 for (int i = 1; i <= n; i++) pos[i].push_back(n + 1);
94 st.insert(node(1, n, 1, n));//插入初始答案集合
95 for (int i = 1; i <= n; i++) {//确定答案中每个数字应该出现几次
96 if (hv[i]) {
97 getnum(i);//确定答案中应该有ans[i]个i
98 merge(i, ans[i]);//从st集合中筛选出含有ans[i]个i的集合
99 }
100 }
101 for (int i = 1; i <= n; i++) {
102 for (int j = 1; j <= ans[i]; j++)
103 printf("%d ", i);
104 }
105 return 0;
106 }

220726 T2 Multisets (思维)的更多相关文章

  1. EZ 2018 03 09 NOIP2018 模拟赛(三)

    最近挺久没写比赛类的blog了 链接:http://211.140.156.254:2333/contest/59 这次的题目主要考验的是爆搜+打表的能力 其实如果你上来就把所有题目都看过一次就可以知 ...

  2. HZ游记

    HZ 游记 Day -1 收拾东西,准备出发. 话说这几天一直比较懒,也没什么心情和效率学习,颓废好几天了,希望到衡水以后能感觉好点. 不知道衡水有没有妹子 非常想看看衡水的样子,但是又害怕封闭式教学 ...

  3. D - Number of Multisets 题解(思维dp)

    题目链接 题目大意 给你一个数k和n,表示用n个\(1/2^i(i=0,1,2.....)\)组成k有多少种方案数 题目思路 这个dp实属巧妙 设\(dp[i][j]表示i个数构成j\) 这i个数可以 ...

  4. 1250 Super Fast Fourier Transform(湘潭邀请赛 暴力 思维)

    湘潭邀请赛的一题,名字叫"超级FFT"最终暴力就行,还是思维不够灵活,要吸取教训. 由于每组数据总量只有1e5这个级别,和不超过1e6,故先预处理再暴力即可. #include&l ...

  5. Day4:T1小技巧(类似于指针操作)T2搜索+小细节

    Day4:其中有很多小技巧get T1 一直没有听到过像这样的小技巧的略专业名词,有点类似于指针操作,之前有碰到过很多这样的题目 每次都是以不同的形式出现,但是感觉思想还是有点接近的吧(就比如某天有一 ...

  6. Day1:T1 模拟 T2 拓扑排序

    T1:模拟 自己第一天的简直跟白痴一样啊...模拟都会打错.. 当时貌似在更新最大值的时候打逗比了... if((sum[x]==max && x<maxh) || sum[x] ...

  7. 带你深入理解STL之空间配置器(思维导图+源码)

    前不久把STL细看了一遍,由于看得太"认真",忘了做笔记,归纳和总结这步漏掉了.于是为了加深印象,打算重看一遍,并记录下来里面的一些实现细节.方便以后能较好的复习它. 以前在项目中 ...

  8. PJ考试可能会用到的数学思维题选讲-自学教程-自学笔记

    PJ考试可能会用到的数学思维题选讲 by Pleiades_Antares 是学弟学妹的讲义--然后一部分题目是我弄的一部分来源于洛谷用户@ 普及组的一些数学思维题,所以可能有点菜咯别怪我 OI中的数 ...

  9. 思维定势--AtCoder Regular Contest 092 D - Two Sequences

    $n \leq 100000$的俩序列,数字范围$2^{28}$,问所有$a_i+b_j$的$n^2$个数字的异或和. 这种东西肯定是按位考虑嘛,从低位开始然后补上进位.比如说第一位俩串分别有$c$个 ...

随机推荐

  1. 意向不到的Dubug妙招

    1.直接dubug到想要到达的位置,直接点击旁边的数字即可. 2.debug后不想重新启动,想重新进入再执行一次debug,可以使用drop frame来删除当前栈,跳到之前的栈再一次进入这个栈. 注 ...

  2. Thread类的常用方法_sleep和创建多线程程序的第二种方式实现Runnable接口

    public static void sleep(long millis);//使当前正在执行的线程以指定的毫秒数暂停(暂时停止执行). 毫秒数结束后线程继续执行 package com.yang.T ...

  3. 6.6 NOI 模拟

    \(T1\)括号序列 --那是,朝思夜想也未尝得到的自由 一个比较常见的转化,考虑如何判断前一段和后一段能够拼成一个合法的括号序列 充要条件: 前半部分,'('看为\(1\), ')'看为\(-1\) ...

  4. php YII2空数组插入报错问题处理 Array to string conversion

    问题描述 前端传空数组 [],php接收后处理不当插入数据库时报错Array to string conversion 参数示例 { "id": 0, //ID整型 "t ...

  5. Taurus.MVC WebAPI 入门开发教程5:控制器安全校验属性【HttpGet、HttpPost】【Ack】【Token】【MicroService】。

    系列目录 1.Taurus.MVC WebAPI  入门开发教程1:框架下载环境配置与运行. 2.Taurus.MVC WebAPI 入门开发教程2:添加控制器输出Hello World. 3.Tau ...

  6. mybatis 08: 返回主键值的insert操作 + 利用UUID获取字符串(了解)

    返回主键值的insert操作 应用背景 图示说明 在上述业务背景下,涉及两张数据表的关联操作:用户表 + 用户积分表 传统操作:在对用户表执行完插入语句后,再次查询该用户的uid,将该uid作为外键, ...

  7. TS 泛型推断好难啊,看看你能写出来不

    前言 最近做东西都在用ts,有时候写比较复杂的功能,如果不熟悉,类型写起来还是挺麻烦的.有这样一个功能,在这里,我们就不以我们现有的业务来举例了,我们还是已Animal举例,来说明场景.通过一个工厂来 ...

  8. Canvas 非线性图形(一):文本

    基础 画布除了绘制图形以外还可以绘制文本,画布中的文本可以设置字体大小.字体格式.对齐方式(横向和纵向对齐方式),并且还可以制作很炫酷的文本,比如渐变文字. 文本有以下三个属性,控制文本的字体大小.字 ...

  9. Excel 文本函数(一):LEFT、RIGHT 和 MID

    文本函数 LEFT.RIGHT 以及 MID 是非常常用的,它们用于截取文本字符串. LEFT(text, [num_chars]) 是从文本字符串的左边开始截取:RIGHT(text, [num_c ...

  10. 刷题记录:Codeforces Round #739 (Div. 3)

    Codeforces Round #739 (Div. 3) 20210907.网址:https://codeforces.com/contest/1560. --(叹). A 不希望出现带" ...