首页 > 代码库 > poj3368线段树
poj3368线段树
题意:给出q次询问,求区间内最长的连续序列。 水题。
1.RMQ 求法 ,st算法 2.线段树,简单的区间合并
#include<iostream>#include<cstdio>#include<cstring>using namespace std;const int maxn = 111111;const int INF = 99999999;int Hash[maxn * 2];int dp[maxn][20];int ans;int sum[maxn];void init(){ for (int i = 0; i < ans; i++) dp[i][0] = sum[i]; for (int j = 1; (1 << j) <= ans; j++){ for (int i = 0; i + (1 << j) - 1 < ans; i++){ dp[i][j] = max(dp[i][j - 1], dp[i + (1 << (j - 1))][j - 1]); } }}int ask(int l, int r){ int k = 0; while ((1 << (k + 1)) <= r - l + 1) k++; return max(dp[l][k], dp[r + 1 - (1 << k)][k]);}int erfen(int a[], int key){ int pos = -1; int l = 0; int r = ans - 1; while (l <= r){ int mid = (l + r) >> 1; if (a[mid] <= key){ pos = mid; l = mid + 1; } else r = mid - 1; } return pos;}int erfen1(int a[], int key){ int pos = -1; int l = 0; int r = ans - 1; while (l <= r){ int mid = (l + r) >> 1; if (a[mid] >= key){ pos = mid; r = mid - 1; } else l = mid + 1; } return pos;}int main(){ int n, q; int Begin[maxn], End[maxn]; int l, r; int a[maxn]; while (scanf("%d", &n), n){ scanf("%d", &q); for (int i = 0; i < n; i++) scanf("%d", &a[i]); a[n] = -INF; int start = 0; ans = 0; for (int i = 0; i < n; i++){ Hash[i] = ans; if (a[i] != a[i + 1]){ sum[ans] = i - start + 1; Begin[ans] = start; End[ans] = i; start = i + 1; ans++; } } init(); for (int i = 0; i < q; i++){ int ret = 0; scanf("%d%d", &l, &r); l--; r--; if (Hash[l] == Hash[r]){ printf("%d\n", r - l + 1); continue; } int lpos = Begin[Hash[l] + 1]; int rpos = End[Hash[r] - 1]; ret = max(ret, lpos - l); ret = max(ret, r - rpos); if (Hash[l] + 1 == Hash[r]){ printf("%d\n", ret); continue; } ret = max(ret, ask(Hash[l] + 1, Hash[r] - 1)); cout << ret << endl; } } return 0;}
线段树
#include <cstdio>#include <cstring>#include <algorithm>#include <climits>#include <string>#include <iostream>#include <map>#include <cstdlib>#include <list>#include <set>#include <queue>#include <stack>#include <math.h>using namespace std;typedef long long LL;#define lson l,mid,rt<<1#define rson mid+1,r,rt<<1|1const int maxn = 111111;int a[maxn];int sum[maxn << 2], lsum[maxn << 2], rsum[maxn << 2];void up(int l, int r, int rt){ lsum[rt] = lsum[rt << 1]; rsum[rt] = rsum[rt << 1 | 1]; sum[rt] = max(sum[rt << 1], sum[rt << 1 | 1]); int mid = (l + r) >> 1; int len = (r - l + 1); if (lsum[rt] == (len - (len >> 1))) if (a[mid] == a[mid + 1]) lsum[rt] += lsum[rt << 1 | 1]; if (rsum[rt] == (len >> 1)) if (a[mid] == a[mid + 1]) rsum[rt] += rsum[rt << 1]; if (a[mid] == a[mid + 1]) sum[rt] = max(sum[rt], rsum[rt << 1] + lsum[rt << 1 | 1]); sum[rt] = max(sum[rt], lsum[rt]); sum[rt] = max(rsum[rt], sum[rt]);}void build(int l, int r, int rt){ if (l == r){ lsum[rt] = rsum[rt] = sum[rt] = 1; scanf("%d", &a[l]); return; } int mid = (l + r) >> 1; build(lson); build(rson); up(l, r, rt);}int ask(int L, int R, int l, int r, int rt){ if (L <= l&&r <= R) return sum[rt]; int ans1 = -1; int ans2 = -1; int ans = -1; int mid = (l + r) >> 1; if (L <= mid) ans1 = ask(L, R, lson); if (R > mid) ans2 = ask(L, R, rson); if (a[mid] == a[mid + 1]) ans = min(rsum[rt << 1], mid - L + 1) + min(lsum[rt << 1 | 1], R - mid); ans = max(ans, ans1); ans = max(ans, ans2); return ans;}int main(){ int n, q, l, r; while (cin >> n, n){ cin >> q; build(1, n, 1); for (int i = 0; i < q; i++){ scanf("%d%d", &l, &r); printf("%d\n", ask(l, r, 1, n, 1)); } } return 0;}
poj3368线段树
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。