Problem 2136 取糖果---FUOJ (线段树+维护)
Posted 啦咯
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Problem 2136 取糖果---FUOJ (线段树+维护)相关的知识,希望对你有一定的参考价值。
http://acm.fzu.edu.cn/problem.php?pid=2136
题目大意: 给你n个袋子每个袋子里都装有糖果,然后呢你可以每次抽取一个连续的一个区间的袋子,然后带走里面最多糖果数目的袋子。
求区间长度从1到n你能带走的糖果数目最坏的情况是多少,也就是求所有区间的最大值的最小值
分析: 如果从小的开始查找他每次只要找到他能覆盖的区间,那么他就是这个区间的最大值,所以我们每次查询这个点就行了
#include<stdio.h> #include<string.h> #include<math.h> #include<algorithm> #include<ctype.h> #include <iostream> #include <map> using namespace std; #define INF 1e9+7 #define Lson r<<1|1 #define Rson r<<1 #define N 101000 int ans[N]; struct node { int l,r,la,lb,Max;///la是这个区间左边连续的个数,lb是右边,Max是区间最大的连续序列 int mid() { return (l+r)/2; } int len() { return (r-l+1); } }a[N*10]; struct Node { int x,y; }P[N]; int cmp(Node c,Node d) { return c.x<d.x; } void BuildTree(int r,int L,int R) { a[r].l = L; a[r].r = R; a[r].la = a[r].lb = a[r].Max = 0; if(L == R) return; BuildTree(Lson, L, a[r].mid()); BuildTree(Rson, a[r].mid()+1, R); } void Qurry(int r,int x,int y) { if(a[r].l == a[r].r) { a[r].la = a[r].lb = a[r].Max = 1; return; } if(y > a[r].mid()) Qurry(Rson, x, y); else Qurry(Lson, x, y); a[r].Max = max(a[Lson].Max, max(a[Rson].Max, a[Lson].lb+a[Rson].la)); a[r].la = a[Lson].la; a[r].lb = a[Rson].lb; if(a[Lson].la == a[Lson].len()) a[r].la += a[Rson].la; if(a[Rson].lb == a[Rson].len()) a[r].lb += a[Lson].lb; } int main() { int T; scanf("%d", &T); while(T --) { int n; scanf("%d", &n); memset(P, 0, sizeof(P)); for(int i=0; i<n; i++) { scanf("%d", &P[i].x); P[i].y = i; } BuildTree(1, 0, n-1); sort(P, P+n, cmp); int m=1; memset(ans, 0, sizeof(ans)); for(int i=0; i<n; i++) { Qurry(1, P[i].x, P[i].y);///查询y点的最大序列 int tmp=a[1].Max; while(m <= tmp) ans[m ++]=P[i].x; } for(int i=1; i<=n; i++) printf("%d\n", ans[i]); } return 0; }
以上是关于Problem 2136 取糖果---FUOJ (线段树+维护)的主要内容,如果未能解决你的问题,请参考以下文章