博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
IIIDX[九省联考2018]
阅读量:6285 次
发布时间:2019-06-22

本文共 7929 字,大约阅读时间需要 26 分钟。

                         

 

题目背景

Osu 听过没?那是Konano 最喜欢的一款音乐游戏,而他的梦想就是有一天自己也能做个独特酷炫的音乐游戏。现在,他在世界知名游戏公司KONMAI 内工作,离他的梦想也越来越近了。

这款音乐游戏内一般都包含了许多歌曲,歌曲越多,玩家越不易玩腻。同时,为了使玩家在游戏上氪更多的金钱花更多的时间,游戏一开始一般都不会将所有曲目公开,有些曲目你需要通关某首特定歌曲才会解锁,而且越晚解锁的曲目难度越高。

题目描述

这一天,Konano 接到了一个任务,他需要给正在制作中的游戏《IIIDX》安排曲目 的解锁顺序。游戏内共有n 首曲目,每首曲目都会有一个难度d,游戏内第i 首曲目会在玩家Pass 第\lfloor \frac{i}{k} \rfloorki⌋ 首曲目后解锁(\lfloor x \rfloorx⌋ 为下取整符号)若\lfloor \frac{i}{k} \rfloorki⌋ = 0,则说明这首曲目无需解锁

举个例子:当k = 2 时,第1 首曲目是无需解锁的(\lfloor \frac{1}{2} \rfloor21⌋ = 0),第7 首曲目需要玩家Pass 第\lfloor \frac{7}{2} \rfloor27⌋ = 3 首曲目才会被解锁。

Konano 的工作,便是安排这些曲目的顺序,使得每次解锁出的曲子的难度不低于作为条件需要玩家通关的曲子的难度,即使得确定顺序后的曲目的难度对于每个i 满足

d_i \geq d_{\lfloor \frac{i}{k} \rfloor}didki

当然这难不倒曾经在信息学竞赛摸鱼许久的Konano。那假如是你,你会怎么解决这份任务呢?

输入输出格式

输入格式:

 

从文件iiidx.in 中读入数据。

第1 行1 个正整数n 和1 个小数k,n 表示曲目数量,k 其含义如题所示。

第2 行n 个用空格隔开的正整数d,表示这n 首曲目的难度。

 

输出格式:

 

输出到文件iiidx.out 中。

输出1 行n 个整数,按顺序输出安排完曲目顺序后第i 首曲目的难度。

若有多解,则输出d1 最大的;若仍有多解,则输出d2最大的,以此类推。

 

输入输出样例

输入样例#1: 
4 2.0114 514 1919 810
输出样例#1: 
114 810 514 1919

说明

 

  第一眼,只会暴力怎么破(哭

  码码码,样例过了。

  第二眼,好像可以看成一棵树,子节点都不比父亲节点小?然后怎么做...

  好像可以贪心!

  码码码...发现我的贪心是错误的(哇哇大哭

  看一眼题解。

  嗯...线段树+二分答案?好像可以。

  码码码...

  对拍一波,没问题!

  交了一波,只有50分(哭得歇斯里地

  嗯。。因为复杂度是两个log,后面几个点T了很正常,但为啥还会有WA的啊!!!

  再看一眼题解。 (想看题解戳)

  重复emmmm....好像重复确实会有问题qwq(为啥对拍不出来啊aaaaa

  认真看了题解思路,emmmm...妙啊!

  码码码...

  debug了一个错误,对拍了两分钟,稳了!

  交上去,A了。几个大数据600多ms,有点危险qaq (果然是自带大常数啊...

 

正解:

 

1 #include
2 #include
3 #include
4 #include
5 #include
6 #define LL long long 7 #define RI register int 8 using namespace std; 9 const int INF = 0x7ffffff ;10 const int N = 500000 + 10 ;11 12 inline int read() {13 int k = 0 , f = 1 ; char c = getchar() ;14 for( ; !isdigit(c) ; c = getchar())15 if(c == '-') f = -1 ;16 for( ; isdigit(c) ; c = getchar())17 k = k*10 + c-'0' ;18 return k*f ;19 }20 21 struct Node {22 int mi, laz ;23 Node *ls, *rs ;24 inline void pushup() {25 mi = min(ls->mi,rs->mi) ;26 }27 inline void pushdown(int l,int r) {28 if(!laz) return ; int mid = (l+r)>>1 ;29 ls->mi += laz, rs->mi += laz ;30 ls->laz += laz, rs->laz += laz ;31 laz = 0 ;32 }33 }pool[N<<1] ;34 inline Node *newNode() {35 static int cnt = 0 ;36 return &pool[++cnt] ;37 }38 Node *build(int l,int r) {39 Node *cur = newNode() ;40 if(l == r) {41 cur->mi = l ;42 } else {43 int mid = (l+r)>>1 ;44 cur->ls = build(l,mid) ; cur->rs = build(mid+1,r) ;45 cur->pushup() ;46 }47 return cur ;48 }49 void change_interval(Node *cur,int l,int r,int a,int b,int x) {50 if(l >= a && r <= b) {51 cur->mi += x, cur->laz += x ; return ;52 }53 cur->pushdown(l,r) ;54 int mid = (l+r)>>1 ;55 if(a <= mid) change_interval(cur->ls,l,mid,a,b,x) ;56 if(b > mid) change_interval(cur->rs,mid+1,r,a,b,x) ;57 cur->pushup() ;58 }59 int query(Node *cur,int l,int r,int k) {60 if(l == r) {61 return cur->mi >= k ? l : l+1 ;62 }63 cur->pushdown(l,r) ;64 int mid = (l+r)>>1 ;65 if(cur->rs->mi >= k) return query(cur->ls,l,mid,k) ;66 else query(cur->rs,mid+1,r,k) ;67 }68 69 int n ; double k ; int hh[N], fa[N], siz[N], ans[N], cnt[N] ;70 71 inline bool cmp1(int s,int t) { return s > t ; }72 int main() {73 n = read() ; scanf("%lf",&k) ;74 for(int i=1;i<=n;i++) hh[i] = read() ;75 sort(hh+1,hh+n+1,cmp1) ;76 for(int i=1;i<=n;i++) fa[i] = floor(i/k), siz[i] = 1 ;77 for(int i=n;i;i--) {78 cnt[i] = hh[i] == hh[i+1] ? cnt[i+1]+1 : 0 ;79 siz[fa[i]] += siz[i] ;80 }81 Node *root = build(1,n) ;82 for(int i=1;i<=n;i++) {83 if(fa[i] && fa[i] != fa[i-1]) change_interval(root,1,n,ans[fa[i]],n,siz[fa[i]]-1) ;84 int x = query(root,1,n,siz[i]) ;85 x += cnt[x], cnt[x]++, x -= (cnt[x]-1) ; ans[i] = x ;86 change_interval(root,1,n,x,n,-siz[i]) ;87 }88 for(int i=1;i<=n;i++) printf("%d ",hh[ans[i]]) ;89 return 0 ;90 }

  一开始竟然忘记pushdown了,好像没睡醒=-=

 

暴力:

1 #include
2 #include
3 #include
4 #include
5 #include
6 #define LL long long 7 #define RI register int 8 using namespace std; 9 const int INF = 0x7ffffff ;10 const int N = 100 + 10 ;11 12 inline int read() {13 int k = 0 , f = 1 ; char c = getchar() ;14 for( ; !isdigit(c) ; c = getchar())15 if(c == '-') f = -1 ;16 for( ; isdigit(c) ; c = getchar())17 k = k*10 + c-'0' ;18 return k*f ;19 }20 int n ; double k ; int pre[N], d[N], res[N] ;21 bitset
vis ; bool flag = 0 ;22 23 void dfs(int x) {24 if(x == n+1) {25 flag = 1 ; 26 for(int i=1;i<=n;i++) printf("%d ",res[i]) ;27 return ;28 }29 for(int i=1;i<=n;i++) {30 if(flag) return ;31 if(!vis[i] && d[i] >= res[pre[x]]) {32 vis[i] = 1 ; res[x] = d[i] ;33 dfs(x+1) ; vis[i] = 0 ;34 }35 }36 }37 38 inline bool cmp1(int s,int t) { return s > t ; }39 int main() {40 n = read() ; scanf("%lf",&k) ;41 for(int i=1;i<=n;i++) {42 d[i] = read() ; pre[i] = (double)i/k ;43 }44 sort(d+1,d+n+1,cmp1) ;45 dfs(1) ;46 return 0 ;47 }

 

二分答案+线段树:

1 #include
2 #include
3 #include
4 #include
5 #include
6 #define LL long long 7 #define RI register int 8 using namespace std; 9 const int INF = 0x7ffffff ; 10 const int N = 500000 + 10 ; 11 12 inline int read() { 13 int k = 0 , f = 1 ; char c = getchar() ; 14 for( ; !isdigit(c) ; c = getchar()) 15 if(c == '-') f = -1 ; 16 for( ; isdigit(c) ; c = getchar()) 17 k = k*10 + c-'0' ; 18 return k*f ; 19 } 20 21 int n ; int d[N], siz[N] ; double k ; bool vis[N] ; 22 vector
v[N] ; 23 24 void dfs1(int x,int fa) { 25 vis[x] = 1 ; int mm = v[x].size() ; siz[x] = 1 ; 26 for(int i=0;i
val ; 38 if(rs) val += rs->val ; 39 } 40 inline void pushdown(int l,int r) { 41 if(!laz) return ; 42 int mid = (l+r)>>1 ; 43 ls->val += laz*(mid-l+1) ; rs->val += laz*(r-mid) ; 44 ls->laz += laz, rs->laz += laz ; 45 laz = 0 ; 46 } 47 }pool[N<<1] ; int a, b, x ; 48 inline Node *newNode() { 49 static int cnt = 0 ; 50 return &pool[++cnt] ; 51 } 52 Node *build(int l,int r) { 53 Node *cur = newNode() ; 54 if(l == r) { 55 cur->val = n-l ; 56 } else { 57 int mid = (l+r)>>1 ; 58 cur->ls = build(l,mid) ; cur->rs = build(mid+1,r) ; 59 cur->pushup() ; 60 } 61 return cur ; 62 } 63 void change_interval(Node *cur,int l,int r) { 64 if(l >= a && r <= b) { 65 cur->laz += x, cur->val += x*(r-l+1) ; return ; 66 } 67 cur->pushdown(l,r) ; int mid = (l+r)>>1 ; 68 if(a <= mid) change_interval(cur->ls,l,mid) ; 69 if(b > mid) change_interval(cur->rs,mid+1,r) ; 70 cur->pushup() ; 71 } 72 int ask_point(Node *cur,int l,int r) { 73 // printf("zzz\n") ; 74 if(l == r) return cur->val ; 75 cur->pushdown(l,r) ; int mid = (l+r)>>1 ; 76 if(x <= mid) return ask_point(cur->ls,l,mid) ; 77 else return ask_point(cur->rs,mid+1,r) ; 78 } 79 80 Node *root ; int ans[N] ; 81 inline bool check(int kk,int xx) { 82 x = kk ; 83 int res = ask_point(root,1,n) ; // printf("res:%d\n",res) ; 84 if(res >= siz[xx]-1) return 1 ; 85 // if(ask_point(root,1,n) >= siz[xx]-1) return 1 ; 86 return 0 ; 87 } 88 89 bool vv[N] ; 90 void dfs2(int xx,int fa) { 91 vis[xx] = 1 ; 92 int L = 1, R = n, res = 0 ; 93 while(L < R) { 94 int mid = (L+R)>>1 ; while(vv[mid]) mid++ ; if(mid > R) { R = (L+R)>>1 ; continue ; } 95 if(check(mid,xx)) res = max(res,mid), L = mid+1 ; 96 else R = mid ; 97 } 98 if(!vv[R] && check(R,xx)) res = max(res,R) ; 99 ans[xx] = d[res], vv[res] = 1 ; // printf("%d:%d %d\n",xx,res,ans[xx]) ;100 a = 1, b = res-1, x = -1 ; if(b) change_interval(root,1,n) ; 101 int mm = v[xx].size() ;102 for(int i=0;i

   // 注释掉的内容为用于调试的代码

转载于:https://www.cnblogs.com/zub23333/p/8778137.html

你可能感兴趣的文章
关于再次查看已做的多选题状态逻辑问题
查看>>
动态下拉菜单,非hover
查看>>
政府安全资讯精选 2017年第十六期 工信部发布关于规范互联网信息服务使用域名的通知;俄罗斯拟建立备用DNS;Google打击安卓应用在未经同意情况下收集个人信...
查看>>
简单易懂的谈谈 javascript 中的继承
查看>>
iOS汇编基础(四)指针和macho文件
查看>>
Laravel 技巧锦集
查看>>
Android 使用 ViewPager+RecyclerView+SmartRefreshLayout 实现顶部图片下拉视差效果
查看>>
Flutter之基础Widget
查看>>
写给0-3岁产品经理的12封信(第08篇)——产品运营能力
查看>>
ArcGIS Engine 符号自动化配置工具实现
查看>>
小程序 · 跳转带参数写法,兼容url的出错
查看>>
flutter error
查看>>
Flask框架从入门到精通之模型数据库配置(十一)
查看>>
10年重新出发
查看>>
2019年-年终总结
查看>>
聊聊elasticsearch的RoutingService
查看>>
让人抓头的Java并发(一) 轻松认识多线程
查看>>
从源码剖析useState的执行过程
查看>>
地包天如何矫正?
查看>>
中间件
查看>>