有\(n\)根长度不一的棍子,q次询问,求\([L,R]\)区间的棍子所能组成的周长最长的三角形。棍长\(\in [1, 1e9]\),n\(\in [1, 1e5]\)。
由于不构成三角形的数组为菲波那切数列,所以当棍数超过44时,长度超过1e9,所以从最大开始数最多不超过45次就能找到构成三角形。所以直接主席树查询区间第k大。复杂度\(O(45 * q * logn)\)。
#include #include #include #include #include #include #include #include #include #include #include #include #include #define ll long long using namespace std; const int maxn = 1e5 + 5; const int INF = 0x3f3f3f3f; const ll MOD = 1e9 + 7; using namespace std; int n, q, tot; int root[maxn]; ll a[maxn]; vector vv; int getId(ll x){ return lower_bound(vv.begin(), vv.end(),x) - vv.begin() + 1; } struct node{ int lson, rson; int sum; }T[maxn * 40]; void update(int l, int r, int &now, int pre, int v, int pos){ T[++tot] = T[pre], T[tot].sum += v, now = tot; if(l == r) return; int m = (l + r) >> 1; if(m >= pos) update(l, m, T[now].lson, T[pre].lson, v, pos); else update(m + 1, r, T[now].rson, T[pre].rson, v, pos); } int query(int l, int r, int pre, int now, int k){ if(l == r) return l; int m = (l + r) >> 1; int sum = T[T[now].lson].sum - T[T[pre].lson].sum; if(sum >= k) return query(l, m, T[pre].lson, T[now].lson, k); else return query(m + 1, r, T[pre].rson, T[now].rson, k - sum); } void init(){ memset(T, 0, sizeof(T)); tot = 0; vv.clear(); } int main(){ while(~scanf("%d%d", &n, &q)){ init(); for(int i = 1; i <= n; i++){ scanf("%lld", &a[i]), vv.push_back(a[i]); } sort(vv.begin(), vv.end()); vv.erase(unique(vv.begin(), vv.end()), vv.end()); for(int i = 1; i <= n; i++){ update(1, vv.size(), root[i], root[i - 1], 1, getId(a[i])); } while(q--){ int l, r; scanf("%d%d", &l, &r); int num = 0; ll ans = -1; ll a1, a2, a3; for(int i = r - l + 1; i >= 1; i--){ if(num == 0){ a3 = query(1, vv.size(), root[l - 1], root[r], i); num++; } else if(num == 1){ a2 = query(1, vv.size(), root[l - 1], root[r], i); num++; } else if(num == 2){ a1 = query(1, vv.size(), root[l - 1], root[r], i); num++; } else{ a3 = a2, a2 = a1; a1 = query(1, vv.size(), root[l - 1], root[r], i); } if(num == 3 && vv[a1 - 1] + vv[a2 - 1] > vv[a3 - 1]){ ans = vv[a1 - 1] + vv[a2 - 1] + vv[a3 - 1]; break; } } printf("%lld\n", ans); } } return 0; }
转载于:https://www.cnblogs.com/KirinSB/p/11249003.html