[九省联考2018] IIIDX 线段树+贪心
题目:
给出 k 和 n 个数,构造一个序列使得 d[i]>=d[i/k] ,并且字典序最大。
分析:
听说,当年省选的时候,这道题挡住了大批的高手,看上去十分简单,实际上那道弯段时间内是转不过来的。
首先,一个套路是,将这个序列的关系抽象成一棵树,i的父亲是floor(i/k),我们要要求子树内部的点的权值都比父亲大。
我们观察子任务的特殊限制,di不一样?
我们想,把原序列从大到小排序,在树上dfs给点赋值,在给一个点赋值时,要在序列上预留出siz[这棵子树]的位置,用来给子树内部的点赋值(排序就是为了方便在序列上预留位置)。
但是,如果有重复的元素就办不了了,比如n=4, k=2 序列是1,1,1,2.
排好应该是1 1 2 1,但是我们上面的方法会排成1 1 1 2
为什么呢?
我们从大到小排序,应该得到2 1 1 1.我们递归,首先是树根节点,需要预留4个位置,所以肯定要选最后一个(1),然后递归到第一个子树(序号为2),size为2,需要在这个子树留两个位置,所以我们把第二个1给了序号2这个位置,然后那个2就给了它的儿子(序号4)但是实际上,我们可以给它留一个1,把这个4给位置3.
我这么分析会很乱,但是我们于情于理考虑一下,我们解决完了位置2,若想字典序最大,我们应该先最大化3这个位置。
所以我们应该在给序号2找到最大值之后,应该为他的子树预留一些值,使这些值在合法的基础上尽可能小。
所以我们应该排序后,建立一个序列c,c[i]的值代表排好序的序列上,i及i左边的所有值还剩下多少个可以选的。
(序列c一开始肯定是1,2,3,4,5……)
然后我们每次为一个点赋值,应该找到最靠左的一个位置i,使所有j>=i满足c[j]>=siz[这个点的子树]。
并且选完之后,要找到这个位置往右最右边和他值相等的那个位置(前提是没有被用过的)。
然后,用区间减法计算贡献,之后接着处理这个点的兄弟节点,没有了兄弟节点之后在进入某个点的子节点。
进入一个子节点时,要将之前预留的位置(区间减去的数值)加回来,但是已经分配出去的(父亲的)权值就不要加回来了。
所以是siz-1
代码:
#include<bits/stdc++.h>
#define db double
using namespace std;
const int N=,inf=1e9;
struct segtree{
int l,r,ls,rs,mn,lz;
}t[N*];int a[N],b[N],ans[N],m,rt;
db k;int n,siz[N],fa[N],cnt[N],o=;
bool cmp(int u,int v){return u>v;}
void pushup(int cur){
int ls=t[cur].ls,rs=t[cur].rs;
t[cur].l=t[ls].l;t[cur].r=t[rs].r;
t[cur].mn=min(t[ls].mn,t[rs].mn);
} void pushdown(int cur){
int ls=t[cur].ls,rs=t[cur].rs,d=t[cur].lz;
t[ls].mn+=d;t[ls].lz+=d;
t[rs].mn+=d;t[rs].lz+=d;
t[cur].lz=;return ;
} void build(int x,int l,int r){
if(l==r){
t[x].l=t[x].r=l;t[x].ls=t[x].rs=-;
t[x].mn=l;return ;
} int mid=l+r>>;
t[x].ls=o++;t[x].rs=o++;
build(t[x].ls,l,mid);build(t[x].rs,mid+,r);
pushup(x);return ;
} void update(int x,int l,int r,int c){
if(l<=t[x].l&&t[x].r<=r)
{t[x].mn+=c;t[x].lz+=c;return ;}
pushdown(x);int mid=t[x].l+t[x].r>>;
if(l<=mid) update(t[x].ls,l,r,c);
if(mid<r) update(t[x].rs,l,r,c);
pushup(x);return ;
} int query(int x,int p){
if(t[x].l==t[x].r)
return t[x].mn>=p?t[x].l:t[x].l+;
pushdown(x);int mid=t[x].l+t[x].r>>;
if(p<=t[t[x].rs].mn) return query(t[x].ls,p);
else return query(t[x].rs,p);return ;
} int main(){
scanf("%d%lf",&n,&k);rt=o++;
for(int i=;i<=n;i++) scanf("%d",&a[i]);
sort(a+,a++n,cmp);build(rt,,n);
for(int i=n-;i;i--)
if(a[i]==a[i+]) cnt[i]=cnt[i+]+;
else cnt[i]=;
for(int i=;i<=n;i++)
fa[i]=(int)floor(i/k),siz[i]=;
for(int i=n;i;i--) siz[fa[i]]+=siz[i];
for(int i=;i<=n;i++){
if(fa[i]&&fa[i]!=fa[i-])
update(rt,ans[fa[i]],n,siz[fa[i]]-);
int x=query(rt,siz[i]);ans[i]=x;
x+=cnt[x];cnt[x]++;x-=(cnt[x]-);
update(rt,x,n,-siz[i]);
} for(int i=;i<=n;i++)
printf("%d ",a[ans[i]]);
return ;
}
贪心+线段树
[九省联考2018] IIIDX 线段树+贪心的更多相关文章
- [BZOJ5249][九省联考2018]IIIDX(线段树)
5249: [2018多省省队联测]IIIDX Time Limit: 40 Sec Memory Limit: 512 MBSubmit: 32 Solved: 17[Submit][Statu ...
- BZOJ5249 九省联考2018IIIDX(线段树+贪心)
显然这形成了一个树形结构.考虑这样一种贪心:按照曲目顺序,每次取消其父亲的预留,并选择当前可选择(保证其子树有合法选择且满足预留)的最大值,然后对其子树预留出大于等于他的一些值.这个做法显然是正确的. ...
- 省选九省联考T2 IIIDX(线段树)
题目传送门:https://www.luogu.org/problemnew/show/P4364 期中考后记:期中考刚考完,感觉不咋滴,年排第3.我抗压力太差了..期末得把rank1抢回来. 本来感 ...
- [luogu] P4364 [九省联考2018]IIIDX(贪心)
P4364 [九省联考2018]IIIDX 题目背景 Osu 听过没?那是Konano 最喜欢的一款音乐游戏,而他的梦想就是有一天自己也能做个独特酷炫的音乐游戏.现在,他在世界知名游戏公司KONMAI ...
- [BZOJ 5252][LOJ 2478][九省联考2018] 林克卡特树
[BZOJ 5252][LOJ 2478][九省联考2018] 林克卡特树 题意 给定一个 \(n\) 个点边带权的无根树, 要求切断其中恰好 \(k\) 条边再连 \(k\) 条边权为 \(0\) ...
- 洛谷P4364 [九省联考2018]IIIDX 【线段树】
题目 [题目背景] Osu听过没?那是Konano最喜欢的一款音乐游戏,而他的梦想就是有一天自己也能做个独特酷炫的音乐游戏.现在 ,他在世界知名游戏公司KONMAI内工作,离他的梦想也越来越近了.这款 ...
- BZOJ.5249.[九省联考2018]iiidx(贪心 线段树)
BZOJ LOJ 洛谷 \(d_i\)不同就不用说了,建出树来\(DFS\)一遍. 对于\(d_i\)不同的情况: Solution 1: xxy tql! 考虑如何把这些数依次填到树里. 首先对于已 ...
- [九省联考2018]IIIDX 贪心 线段树
~~~题面~~~ 题解: 一开始翻网上题解看了好久都没看懂,感觉很多人都讲得不太详细,所以导致一些细节的地方看不懂,所以这里就写详细一点吧,如果有不对的or不懂的可以发评论在下面. 首先有一个比较明显 ...
- [九省联考2018]IIIDX
题目描述 这一天,Konano接到了一个任务,他需要给正在制作中的游戏<IIIDX>安排曲目的解锁顺序.游戏内共有n首曲目 ,每首曲目都会有一个难度d,游戏内第i首曲目会在玩家Pass第t ...
随机推荐
- 第三篇 Nosql讲解之windows下Memcached和Memcache的区别安装(二)
一.Memcached和Memcache的区别: 网上关于Memcached和Memcache的区别的理解众说纷纭,我个人的理解是: Memcached是一个内存缓存系统,而Memcache是php的 ...
- Execution failed for task ':app:lintVitalRelease'.
解决方法:在build.gradle文件的android部分添加如下代码: lintOptions { checkReleaseBuilds false abortOnError false} 最后成 ...
- E - Multiplication Puzzle
#include <iostream> #include <algorithm> #include <cstring> #include <cstdio> ...
- ZOJ 4033 CONTINUE...?(The 15th Zhejiang Provincial Collegiate Programming Contest Sponsored by TuSimple)
#include <iostream> #include <algorithm> using namespace std; ; int a[maxn]; int main(){ ...
- [coci2015-2016 coii] Palinilap【字符串 哈希】
传送门:http://www.hsin.hr/coci/archive/2015_2016/ 进去之后点底下的那个.顺带说一句,题目既不是一个英文单词,也不是克罗地亚单词,估计只是从回文串的英文单词p ...
- 为什么static方法中不可以调用非static方法
Java是面向对象的语言,所有的变量,方法都是针对对象而言的.一般来说,要调用一个方法,你需要new 这个方法的对象. 什么时候用static? 如果你想要: 对于一个类的所有对象共享一个变量或者是方 ...
- 安装dubbo的监控中心dubbo-monitor-simple
1.下载dubbo-monitor-simple 2.修改配置指定注册中心地址 进入dubbo-monitor-simple\src\main\resources\conf目录修改 dubbo.pro ...
- [译]Understanding ECMAScript6 迭代器与生成器(未完)
迭代器在许多编程语言中被作为一种更易处理数据集合的方式被使用.在ECMAScript6中,JavaScript添加了迭代器,将其作为此语言的一个重要特征.当再加上新的方法和新的集合类型(比如集合与映射 ...
- 使用Yeoman 创建 angular应用
一.安装 Yeoman npm install yo -g 如果提示当前nodejs版本和npm版本太低,先升级下再安装yeoman. 安装成功后,默认只有webapp和Mocha这两个生成器. 二. ...
- 第十二章 设计用户界面 之 设计自适应的UI布局
1. 概述 随着手机和平板设备的日益普及,使得开发者不得不考虑MVC网站在移动设备上的展示. 本章内容包括:运行在多种设备上的程序(屏幕分辨率,CSS,HTML).设计手机端Web程序. 2. 主要内 ...