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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

BZOJ-3110-K大数查询-ZJOI2013-整体二分

發布時間:2025/3/15 编程问答 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 BZOJ-3110-K大数查询-ZJOI2013-整体二分 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

描述

有N個位置,M個操作。操作有兩種,每次操作如果是1 a b c的形式表示在第a個位置到第b個位置,每個位置加入一個數c

如果是2 a b c形式,表示詢問從第a個位置到第b個位置,第C大的數是多少。


分析

  • 今天終于看懂了一個整體二分的題目. 發現這真是一種很BT的做法.
  • 二分答案區間(L, R),?判斷中間值M = L+(R-L)/2. 每次清空線段樹(直接在根節點上打刪除標記, 不要用memset直接清, 會T..). ?線段樹維護的是在區間(a, b)中比二分的答案M大的數有多少.?處理在(l, r)中的操作, 如果是插入(a, b, c), 判斷c和M的大小, c大于M的話在線段樹(a, b)區間打增加標記表示+1, 同時操作類型標記為1, c不大于M操作類型標記為0; 如果是查詢(a, b, c)操作, 當在線段樹(a, b)區間和大于c則說明比M大的超過k個, 那么答案一定比M大, 操作類型標記為1, 否則標記為0.
  • 將所有標記為0的點去下一層(L, M)繼續 (可以直接按類型sort, 也可以借鑒歸并排序的思想O(n)的歸并), 標記為1的點去(M+1, R)繼續二分.
  • 當答案區間(L = R)時, 操作區間所有的查詢操作的答案都為L.
  • 另 : 1. 在線段樹操作時傳入太多參數會嚴重拖慢效率.
  • ? ? ? 2. 在結構體里定義的宏在外面一樣用.

代碼
#include #include #include using namespace std;const int maxn = 50000 + 10;#define M (L+((R-L)>>1))struct SegmentTree {int y1, y2;int sumv[maxn<<2], addv[maxn<<2];bool clr[maxn<<2];void init() {sumv[1] = addv[1] = 0;clr[1] = 1;}#define lc (o<<1)#define rc (o<<1^1)void update(int o) {sumv[o] = sumv[lc] + sumv[rc];}void pushdown(int o, int L, int R) {if(clr[o]) {sumv[lc] = sumv[rc] = addv[lc] = addv[rc] = 0;clr[lc] = clr[rc] = 1;clr[o] = 0;}if(addv[o]) {int& x = addv[o];addv[lc] += x;addv[rc] += x;sumv[lc] += (M-L+1) * x;sumv[rc] += (R-M) * x;x = 0;}}void modify(int o, int L, int R) {if(y1 <= L && R <= y2) {addv[o]++;sumv[o] += (R-L+1);} else {pushdown(o, L, R);if(y1 <= M) modify(lc, L, M);if(y2 > M) modify(rc, M+1, R);update(o);}}int query(int o, int L, int R) {if(y1 <= L && R <= y2) return sumv[o];pushdown(o, L, R);int ret = 0;if(y1 <= M) ret += query(lc, L, M);if(y2 > M) ret += query(rc, M+1, R);return ret;}} seg;struct Node {int opt, id, l, r, v, k;bool operator < (const Node& rhs) const {if(k != rhs.k) return k < rhs.k;return id < rhs.id;} } qst[maxn];int n, m; int ans[maxn];void solve(int L, int R, int l, int r) {if(l > r) return;if(L == R) {for(int i = l; i <= r; i++) {Node& x = qst[i];if(x.opt == 2) ans[x.id] = L;}return;}seg.init();int t = l-1;for(int i = l; i <= r; i++) {Node& x = qst[i];if(x.opt == 1) {if(x.v > M) {seg.y1 = x.l;seg.y2 = x.r;seg.modify(1, 1, n);x.k = 1;} else {x.k = 0; t++;}} else {seg.y1 = x.l;seg.y2 = x.r;int s = seg.query(1, 1, n);if(x.v <= s) x.k = 1;else x.k = 0, t++, x.v -= s;}}sort(qst + l, qst + r + 1);solve(L, M, l, t);solve(M+1, R, t+1, r); }int main() {scanf("%d %d", &n, &m);for(int i = 1; i <= m; i++) {int opt, l, r, v;scanf("%d %d %d %d", &opt, &l, &r, &v);qst[i] = (Node) {opt, i, l, r, v};}memset(ans, -1, sizeof(ans));solve(0, n, 1, m);for(int i = 1; i <= m; i++)if(ans[i] != -1) printf("%d\n", ans[i]);return 0; }

總結

以上是生活随笔為你收集整理的BZOJ-3110-K大数查询-ZJOI2013-整体二分的全部內容,希望文章能夠幫你解決所遇到的問題。

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