FZU Problem 2136 取糖果 2种做法
来源:互联网 发布:ios上python编辑器推荐 编辑:程序博客网 时间:2024/05/17 03:26
有N个袋子放成一排,每个袋子里有一定数量的糖果,lzs会随机选择连续的几个袋子,然后拿走这些袋子中包含最多糖果的袋子。现问你,在选择x个袋子的情况下,lzs最坏情况下,也就是最少会拿到多少个糖果?对于x取值为1到n都分别输出答案。
第一行一个整数T,表示有T组数据。
每组数据先输入一行一个整数N(1<=N<=100000),表示袋子数,接下来一行输入N个正整数,输入的第i个数表示第i个袋子所装的糖果数。
每组数据输出n行,第i行表示lzs随机取连续的i个袋子时的最坏情况下能拿到的糖果数。
1 5 1 3 2 4 5
1 3 3 4 5
题意有点绕...大概就是对于一个d,取一段连续的d个数,然后从中选择最大的。现考虑所有长度为d的子段,问这些段数中最大的数中的最小的数是什么。对于d取值为1到n都要输出答案。
首先按从小到大的顺序排序, 依次删除, 删除前查看下,这个点的范围域, 即左右共删除了几个,
设 d = 删除的点数+本身为范围域, 假如d以前没更新过, 则连续取d的最坏值(暂时)为这个点的值
例如样例: 1 3 2 4 5
从小到大删除点, 先删除最小点, 以下标记黄色:
1 3 2 4 5
左右都没删东西, d=1 所以连续取1个最坏值为1, 接下来删除2
1 3 2 4 5
d=1 因为已经更新过, 更新为2的话肯定比原来的大了, 不是最坏值, 所以不更新, 再删除3
1 3 2 4 5
d=3 所以连续取3个的最坏值为3, 再删除4
1 3 2 4 5
d=4 所以连续取4个的最坏值为4, 最后删除5
1 3 2 4 5
d=5 所以连续取5个的最坏值为5
最后从后往前for一遍, 使连续d+1个的值大于等于连续d个的值
中间操作, 可以借助链表的结构
#define Max(a,b) ((a)>(b)?(a):(b))#define Min(a,b) ((a)<(b)?(a):(b))using namespace std;typedef long long LL ;const int Max_N = 100018 ;int N ;int ans[Max_N] ;struct List{ int Left ; int Right ;};struct Node{ int num ; int id ; friend bool operator < (const Node A ,const Node B){ return A.num < B.num ; }};List lis[Max_N] ;Node node[Max_N] ;bool is_delete[Max_N] ;int find_Left(int id){ if(is_delete[id]==0) return id ; else return lis[id].Left = find_Left(lis[id].Left) ;}int find_Right(int id){ if(is_delete[id]==0) return id ; else return lis[id].Right = find_Right(lis[id].Right) ;}int main(){ int T ; scanf("%d",&T) ; while(T--){ scanf("%d",&N) ; fill(is_delete,is_delete+5+N,0) ; fill(ans,ans+5+N ,-1) ; for(int i=1 ; i <= N ; i++){ scanf("%d",&node[i].num) ; lis[i].Left = i-1 ; lis[i].Right = i+1 ; node[i].id = i ; } sort(node+1,node+1+N) ; for(int i = 1 ;i <= N ; i++){ int id = node[i].id ; int L = find_Left(lis[id].Left) ; int R = find_Right(lis[id].Right) ; int continue_num = R-L-1 ; if(ans[continue_num] == -1) ans[continue_num] = node[i].num ; is_delete[id] = 1 ; } for(int i= N-1 ; i >= 1 ; i--){ if(ans[i] == -1 || ans[i]>ans[i+1]) ans[i] = ans[i+1] ; } for(int i = 1 ; i <= N ; i++) printf("%d\n",ans[i]) ; } return 0 ;}
线段树的做法
先预处理下,对每个位置i处理出一个区间[L,R]。表示这个范围中,a[i]是最大的,然后用线段树维护下最大值,循环1到n,对i,用a[i]的值去更新区间【1,R[i]-L[i]+1】的最小值。最后循环每次查询第i个位置的最小值是多少就行了......
const int maxn = 100008 ;const int inf = 100000000 ;int x[maxn] , l[maxn] , r[maxn] ;int minx[maxn<<2] ;void update(int l , int r , int c , int L , int R , int t){ if(l == L && r == R){ minx[t] = min(minx[t] , c) ; return ; } int M = (L + R) >> 1 ; if(r <= M) update(l , r , c , L , M , t<<1) ; else if(l > M) update(l , r , c , M+1 , R , t<<1|1) ; else{ update(l , M , c , L , M , t<<1) ; update(M+1 , r , c , M+1 , R , t<<1|1) ; }}int ask(int i , int L , int R , int t){ if(L == R) return minx[t] ; int M = (L + R) >> 1 ; int s = minx[t] ; if(i <= M) s = min(s , ask(i , L , M , t<<1)) ; if(i > M) s = min(s , ask(i , M+1 , R , t<<1|1)) ; return s ;}int main(){ int t , n , i , j; cin>>t ; while(t--){ scanf("%d" ,&n) ; for(i = 1 ; i <= n ; i++) scanf("%d" ,&x[i]) ; for(i = 1 ; i <= n ; i++){ l[i] = i ; j = i - 1 ; while(j >= 1 && x[j] <= x[i]){ l[i] = l[j] ; j = l[j] - 1 ; } } for(i = n ; i >= 1 ; i--){ r[i] = i ; j = i + 1 ; while(j <= n && x[j] <= x[i]){ r[i] = r[j] ; j = r[j] + 1 ; } } memset(minx , 63 , sizeof(minx)) ; for(i = 1 ; i <= n ; i++) update(1 , r[i]-l[i]+1 , x[i] , 1 , n , 1) ; for(i = 1 ; i <= n ; i++) printf("%d\n" , ask(i , 1 , n , 1)) ; } return 0 ;}
0 0
- FZU Problem 2136 取糖果 2种做法
- FZU 2136 取糖果
- FZU 2136 取糖果
- FZU Problem 2136 取糖果(线段树离散化,区间合并)
- FZU 2136 取糖果(线段树)
- fzu 2136 取糖果(线段树)
- 【单调栈】fzu 2136取糖果
- fzu 11月赛E 2136 取糖果 线段树
- FZU 2136 取糖果 (排序+并查集)
- FOJ 2136 取糖果(单调栈)
- fzu-2116 买糖果(背包)
- FZU Problem 2104 Floor problem
- FZU problem 1985 LCP Problem
- fzu problem 1013 rpgame
- FZU Problem 2110 Star
- FZU Problem 2054 拳王
- FZU 1692 Key problem
- FZU 2104 Floor problem
- Ubuntu /etc/fstab文件说明
- 做软件“产品”开发需要哪些文档?
- 队列以一种先进先出的方式管理数据
- OCP-1Z0-051 第75题 ROUND和RPAD函数
- 分鱼问题
- FZU Problem 2136 取糖果 2种做法
- Eclipse几个常用设置
- UVA10717- Mint
- 安卓应用开发中使用代码接通电话
- XShell工具sftp使用
- visual studio代码智能提示没有了?!!!!
- 拿来主义往往束缚人们对新事物的研究与发现 - 记于 OpenGLES 模型移动研究过程中的感悟
- linux驱动那些事儿之驱动分析之前的磨刀工
- Eclipse导入android项目,报invalid project description错误的解决办法