日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

【FJOI2016】【BZOJ4408】神秘数

發布時間:2023/12/14 编程问答 18 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【FJOI2016】【BZOJ4408】神秘数 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

【題目鏈接】

  • BZOJ4408(權限題)

【前置技能】

  • 主席樹

【題解】

  • 首先先考慮一種時間復雜度為O(QNlogN)O(QNlogN)的暴力做法:將所有數按從小到大排序,考慮做到第pospos位前綴和為SposSpos,并且前面的數能表示[1,Spos][1,Spos]中的所有數,那么如果apos+1Spos+1apos+1≤Spos+1,則前pos+1pos+1個數可以表示[1,Spos+1][1,Spos+1]中的所有數,否則,第一個不能被表示的神秘數就是Spos+1Spos+1。
  • 那么我們考慮如何加速這個過程:若目前的前綴和為SS,那么我們可以一次性將所有小于等于SS的數求和,作為新的SS重復上述過程。顯然這個過程實質上和上面依次加入的過程是一樣的,那么這么做是否要比暴力快呢?發現這么做最壞的情況是斐波那切數列,我們可以認為這是O(logai)O(log∑ai)級別的。
  • 那么對于本題,要求區間詢問,支持區間求小于等于某個數的和,我們就可以用主席樹維護。注意數的范圍打到了109109,建主席樹的時候可以考慮離散化或者動態開節點。
  • 時間復雜度O(QlogNlogai)O(QlogNlog∑ai)

【代碼】

#include<bits/stdc++.h> #define INF 0x3f3f3f3f #define LL long long #define MAXN 100010 #define MAXLOG 30 using namespace std; int N, w[MAXN], Q; template <typename T> void chkmin(T &x, T y){x = min(x, y);} template <typename T> void chkmax(T &x, T y){x = max(x, y);} template <typename T> void read(T &x){x = 0; int f = 1; char ch = getchar();while (!isdigit(ch)) {if (ch == '-') f = -1; ch = getchar();}while (isdigit(ch)) {x = x * 10 + ch - '0'; ch = getchar();}x *= f; }struct Segment_Tree{struct info{int ls, rs, sum;}a[MAXN * MAXLOG];int n, cnt, root[MAXN];void update(int &pos, int old, int l, int r, int p){pos = ++cnt, a[pos] = a[old], a[pos].sum += p;if (l == r) return;int mid = (l + r) >> 1;if (p <= mid) update(a[pos].ls, a[old].ls, l, mid, p);else update(a[pos].rs, a[old].rs, mid + 1, r, p);}void init(int x){n = x, cnt = 0;root[0] = ++cnt;for (int i = 1; i <= N; ++i)update(root[i], root[i - 1], 1, n, w[i]);}int query(int lp, int rp, int l, int r, int ll, int rr){if (l == ll && r == rr) return a[rp].sum - a[lp].sum;int mid = (l + r) >> 1;if (rr <= mid) return query(a[lp].ls, a[rp].ls, l, mid, ll, rr);else if (ll > mid) return query(a[lp].rs, a[rp].rs, mid + 1, r, ll, rr);else return query(a[lp].ls, a[rp].ls, l, mid, ll, mid) + query(a[lp].rs, a[rp].rs, mid + 1, r, mid + 1, rr);}int query(int l, int r, int L, int R){if (R > n) R = n;return query(root[l - 1], root[r], 1, n, L, R);}int work(int l, int r){int ret = 1;while (1){int tmp = query(l, r, 1, ret);if (tmp >= ret) ret = tmp + 1;else break;}return ret;} }sgt;int main(){read(N);int maxn = 0;for (int i = 1; i <= N; ++i)read(w[i]), chkmax(maxn, w[i]);sgt.init(maxn);read(Q);while (Q--){int l, r; read(l), read(r);printf("%d\n", sgt.work(l, r));}return 0; }

總結

以上是生活随笔為你收集整理的【FJOI2016】【BZOJ4408】神秘数的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。