題意:戳這裏php
思路:能夠用cdq分治(很明顯這種模型妹紙分治法很解決)。。不過爲了學習樹套樹特意寫了一下。。node
所謂的樹套樹也第一層(最外層)普通的維護的是一個node,而樹套樹維護的是一個數據結構(一棵樹)。。ios
樹套樹通常能夠解決2維模型。。1維的話也就是普通的數據結構了。數據結構
好比poi07 的mokia其實就是一個2爲線段樹,不夠空間不夠因此必須寫成樹套樹。。ide
本題的話如把權值當作一維,原本位置當作1維,那麼其實也是2維模型。學習
插入就等價於每次在一條x=c 橫線的[a,b]之間每一個位置都插入1遍spa
查詢等價於求第k大的在哪條橫線上。。 code
對於這一題的話,能夠以下:blog
首先最外層維護的是權值構成的線段樹,內存
而對於每一個權值,又對應着一棵線段樹,不過這個線段樹是下標線段樹
因爲空間有限,因此有用到才動態分配內存。。
而後每次插入的話在最外層包括value=c的logn段裏面都插入,
查詢的每次二分,左邊過小右邊找,正好從外層線段樹從上到下。。
時間複雜度O(mlog2n)
code:
1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 #include<cstdlib> 5 #include<cmath> 6 #include<algorithm> 7 #include<string> 8 #include<map> 9 #include<set> 10 #include<vector> 11 #include<queue> 12 #include<stack> 13 #define M0(x) memset(x, 0, sizeof(x)) 14 using namespace std; 15 #define lson lc[rt], l, m 16 #define rson rc[rt], m+1, r 17 const int N = 51000, M = 15000000; 18 int rt[N<<2], sum[M], lc[M], rc[M], lz[M]; 19 int n, m, L, R, cnt, c; 20 21 inline void push_up(const int& rt){ 22 sum[rt] = sum[lc[rt]] + sum[rc[rt]]; 23 } 24 25 inline void push_down(const int &rt, const int& l, const int &r){ 26 if (lz[rt]){ 27 if (!lc[rt]) lc[rt] = ++cnt; 28 if (!rc[rt]) rc[rt] = ++cnt; 29 sum[lc[rt]] += lz[rt] * ((r-l+2)>>1), sum[rc[rt]] += lz[rt] * ((r-l+1)>>1); 30 lz[lc[rt]] += lz[rt], lz[rc[rt]] += lz[rt]; 31 lz[rt] = 0; 32 } 33 } 34 35 int query(const int& rt,const int& l, const int& r){ 36 if (!rt) return 0; 37 if (L <= l && r <= R) return sum[rt]; 38 int m = (l + r) >> 1, tmp1 = 0, tmp2 = 0; 39 push_down(rt, l, r); 40 if (L <= m) tmp1 = query(lson); 41 if (R > m) tmp2 = query(rson); 42 return tmp1 + tmp2 + (min(R, r) - max(l, L) + 1) * lz[rt]; 43 } 44 45 int query(int k){ 46 int l = 1, r = n, mid, cur = 1, tmp; 47 while (l <= r){ 48 if (l == r) return l; 49 mid = (l + r) >> 1; 50 tmp = query(rt[cur<<1], 1, n); 51 if (tmp >= k) r = mid, cur <<= 1; 52 else l = mid + 1, k -= tmp, cur = cur<<1|1; 53 } 54 return l; 55 } 56 57 void update(int &rt,const int& l,const int& r){ 58 if (!rt) rt = ++cnt; 59 if (L <= l && r <= R){ 60 sum[rt] += (r - l + 1), ++lz[rt]; 61 return; 62 } 63 int m = (l + r) >> 1; 64 push_down(rt, l, r); 65 if (L <= m) update(lson); 66 if (R > m) update(rson); 67 push_up(rt); 68 } 69 70 void insert(const int& c){ 71 int l = 1, r = n, cur = 1, mid; 72 while (l <= r){ 73 update(rt[cur], 1, n); 74 if (l == r) break; 75 mid = (l + r) >> 1; 76 if (c <= mid) cur<<= 1, r = mid; 77 else l = mid + 1, cur = cur<<1|1; 78 } 79 } 80 81 void solve(){ 82 cnt = 0; 83 int op; 84 while (m--){ 85 scanf("%d%d%d%d", &op, &L, &R, &c); 86 if (op==1) c = n - c + 1, insert(c); 87 else printf("%d\n", n - query(c) + 1); 88 } 89 } 90 91 int main(){ 92 freopen("a.in", "r", stdin); 93 freopen("a.out", "w", stdout); 94 while (scanf("%d%d", &n, &m) != EOF){ 95 solve(); 96 } 97 return 0; 98 }
code
1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 #include<cstdlib> 5 #include<cmath> 6 #include<algorithm> 7 #include<string> 8 #include<map> 9 #include<set> 10 #include<vector> 11 #include<queue> 12 #include<stack> 13 #define M0(x) memset(x, 0, sizeof(x)) 14 using namespace std; 15 #define lson lc[rt], l, m 16 #define rson rc[rt], m+1, r 17 const int N = 50100, M = 15000000; 18 int rt[N<<2], sum[M], lc[M], rc[M], lz[M]; 19 int n, m, L, R, cnt, c; 20 21 int query(const int& rt,const int& l, const int& r){ 22 if (!rt) return 0; 23 if (L <= l && r <= R) return sum[rt]; 24 int m = (l + r) >> 1, tmp1 = 0, tmp2 = 0; 25 if (L <= m) tmp1 = query(lson); 26 if (R > m) tmp2 = query(rson); 27 return tmp1 + tmp2 + (min(R, r) - max(l, L) + 1) * lz[rt]; 28 } 29 30 int query(int k){ 31 int l = 1, r = n, mid, cur = 1, tmp; 32 while (l <= r){ 33 if (l == r) return l; 34 mid = (l + r) >> 1, tmp = query(rt[cur<<1], 1, n); 35 if (tmp >= k) r = mid, cur <<= 1; 36 else l = mid + 1, k -= tmp, cur = cur<<1|1; 37 } 38 return l; 39 } 40 41 void update(int &rt,const int& l,const int& r){ 42 if (!rt) rt = ++cnt; 43 if (L <= l && r <= R){ 44 sum[rt] += (r - l + 1), ++lz[rt]; 45 return; 46 } 47 int m = (l + r) >> 1; 48 if (L <= m) update(lson); 49 if (R > m) update(rson); 50 sum[rt] = sum[lc[rt]] + sum[rc[rt]] + lz[rt] * (r - l + 1); 51 } 52 53 void insert(const int& c){ 54 int l = 1, r = n, cur = 1, mid; 55 while (l <= r){ 56 update(rt[cur], 1, n); 57 if (l == r) break; 58 mid = (l + r) >> 1; 59 if (c <= mid) cur<<= 1, r = mid; 60 else l = mid + 1, cur = cur<<1|1; 61 } 62 } 63 64 void solve(){ 65 cnt = 0; 66 int op; 67 while (m--){ 68 scanf("%d%d%d%d", &op, &L, &R, &c); 69 if (op==1) c = n - c + 1, insert(c); 70 else printf("%d\n", n - query(c) + 1); 71 } 72 } 73 74 int main(){ 75 freopen("a.in", "r", stdin); 76 freopen("a.out", "w", stdout); 77 while (scanf("%d%d", &n, &m) != EOF){ 78 solve(); 79 } 80 return 0; 81 }
第一個lazy直接下放慢成狗。。學習了一下優美姿式快了很多。。