codeforce 1156E Special Segments of Permutation
题面:

题目大意:
给你一个长度为n的序列,需要你找出一个特殊的区间[L,R],满足这个区间的最大值等于这个区间两边的和。
问你有多少个这样的区间。
解题思路:
对于一个区间[L,R],找出区间的最大值的下标,以此为分界线分为左边,右边。
在长度较小的一边暴力寻找另一边是不是有满足条件的值,有就++ans。
然后再将左边和右边看成一个新的区间,去寻找答案。
递归下去,直到区间足够的小时返回答案。
算法:
主席树,递归。
利用主席树快速计算区间最大值,并通过at数组找出最大值的位置。
同时利用主席树快速查询区间是否存在某个值。
AC代码:
#include<iostream> #include<algorithm> using namespace std; typedef long long ll; const int MAXN = 200000; struct node { int ls, rs; int sum; }; int num[MAXN + 5], tree[MAXN + 5], at[MAXN + 5]; node T[MAXN * 20]; int cnt = 0, n = 0; void updata(int l, int r, int last, int &now, int x) { now = ++cnt; T[cnt] = T[last]; ++T[cnt].sum; if (l >= r) return; int mid = (l + r) >> 1; if (x <= mid) updata(l, mid, T[last].ls, T[now].ls, x); else updata(mid + 1, r, T[last].rs, T[now].rs, x); } bool query(int l, int r, int start, int end, int x) { if (T[end].sum <= T[start].sum) return false; if ((l == r) && (l == x) && (T[end].sum > T[start].sum)) return true; int mid = (l + r) >> 1; if (x <= mid) return query(l, mid, T[start].ls, T[end].ls, x); else return query(mid + 1, r, T[start].rs, T[end].rs, x); } int query_max(int l, int r, int start, int end) { if (l == r) return r; if ((T[T[end].rs].sum > T[T[start].rs].sum)) return query_max(((l + r) >> 1) + 1, r, T[start].rs, T[end].rs); else return query_max(l,(l+r)>>1, T[start].ls, T[end].ls); } int solve(int l, int r) { if ((r - l) < 2) return 0; int id = at[query_max(1, n, tree[l - 1], tree[r])], ans = 0; int length_l = id - l, length_r = r - id; if (length_l > length_r) { for (int i = id + 1; i <= r; ++i) { if (query(1, n, tree[l - 1], tree[id-1], num[id] - num[i])) ++ans; } } else { for (int i = l; i < id; ++i) { if (query(1, n, tree[id], tree[r], num[id] - num[i])) ++ans; } } ans += solve(l, id - 1); ans += solve(id + 1, r); return ans; } int main() { scanf_s("%d", &n); for (int i = 1; i <= n; ++i) { scanf_s("%d", num + i); at[num[i]] = i; updata(1, n, tree[i - 1], tree[i], num[i]); } int l = 0, r = 0, x = 0; printf("%d\n", solve(1, n)); }
浙公网安备 33010602011771号