HDU6601
-
题目
-
分析
多校题。
判断三角形能不能构成, F i b o n a c c i Fibonacci Fibonacci 数列 : 1 , 1 , 2 , 3 , 5 , 8 , 13... 1,1,2,3,5,8,13... 1,1,2,3,5,8,13... 数列中任意三个数构不成三角形,所以看最差的情况也就是第 44 44 44 位数超过了范围。所以只用判断区间中最大的 44 44 44 位数就可以了,在 44 44 44 位数中快速判断能否构成三角形且周长最长的方法是:将这 44 44 44 个数从大到小排序: a , b , c , d , e , f . . . a,b,c,d,e,f... a,b,c,d,e,f... 先判断 a , b , c a,b,c a,b,c 可不可以,看 a a a 是否小于 b + c b + c b+c ,若小于则就是 a + b + c a + b + c a+b+c 就是答案,若 a a a 大于等于 b + c b + c b+c ,因为 b , c b,c b,c 已经是数列中第二大和第三大的了,那么随便在后面取什么数都不可能大于 a a a 了。再判断 b , c , d b,c,d b,c,d 以此类推。。。
前 44 44 44 大用主席树维护。。这里代码维护的第 k k k 小,一样的。。。
模板扒的- 代码
const int N = 2e5 + 5; int a[N], b[N]; int root[N]; int cnt = 0; int tot = 0; int q, n; std::vector<ll> v; struct ps_tree { int lc; int rc; int cnt; } tree[N * 40]; int build(int l, int r) { int pos = ++cnt; if (l == r) { tree[pos].cnt = 0; return pos; } int mid = (l + r) >> 1; tree[pos].lc = build(l, mid); tree[pos].rc = build(mid + 1, r); return pos; } int update(int ed, int l, int r, int val) { int pos = ++cnt; tree[pos] = tree[ed]; if (l == r) { tree[pos].cnt++; return pos; } int mid = (l + r) >> 1; if (val <= mid) tree[pos].lc = update(tree[ed].lc, l, mid, val); else tree[pos].rc = update(tree[ed].rc, mid + 1, r, val); tree[pos].cnt = tree[tree[pos].lc].cnt + tree[tree[pos].rc].cnt; return pos; } ll query(int p, int q, int l, int r, int k) { if (l == r) return l; int mid = (l + r) >> 1; int lcnt = tree[tree[p].lc].cnt - tree[tree[q].lc].cnt; if (k <= lcnt) return query(tree[p].lc, tree[q].lc, l, mid, k); else return query(tree[p].rc, tree[q].rc, mid + 1, r, k - lcnt); } bool cmp(int a, int b) { return a > b; } int main () { while (~scanf("%d %d", &n, &q)) { tot = 0; for (int i = 1; i <= n; i++) { read(a[i]); b[++tot] = a[i]; } sort(b + 1, b + tot + 1); tot = unique(b + 1, b + tot + 1) - (b + 1); root[0] = build(1, tot); for (int i = 1; i <= n; i++) { int pos = lower_bound(b + 1, b + tot + 1, a[i]) - b; root[i] = update(root[i - 1], 1, tot, pos); } for (int i = 1; i <= q; i++) { int l, r; read(l); read(r); if (r - l + 1 <= 2) { printf("-1\n"); continue; } if (r - l + 1 > 44) { v.clear(); for (int i = (r - l + 1); i >= (r - l + 1 - 44); i--) { v.push_back(b[query(root[r], root[l - 1], 1, tot , i)]); } sort(v.begin(), v.end(), cmp); ll ans = 0; int flag = 0; for (int i = 0; i <= v.size() - 3; i++) { if (v[i] < (ll)v[i + 1] + v[i + 2]) { ans = (ll)v[i] + v[i + 1] + v[i + 2]; flag = 1; break; } } if (!flag) ans = -1; printf("%lld\n", ans); } else { v.clear(); for (int i = (r - l + 1); i >= 1; i--) { v.push_back(b[query(root[r], root[l - 1], 1, tot, i)]); } sort(v.begin(), v.end(), cmp); ll ans = 0; int flag = 0 ; for (int i = 0; i <= v.size() - 3; i++) { if (v[i] < (ll)v[i + 1] + v[i + 2]) { ans = (ll)v[i] + v[i + 1] + v[i + 2]; flag = 1; break; } } if (!flag) ans = -1; printf("%lld\n", ans); } } } return 0 ; }
-
题型
主席树 + 暴力