zoukankan      html  css  js  c++  java
  • 【BZOJ3196】【Luogu P3380】 【模板】二逼平衡树(树套树)

    做数据结构一定要平((fo))((de))((yi))((pi))。。。不然会四处出锅的(QAQ)

    写法:线段树套平衡树,(O(Nlog^3N))。五个操作如果是对于整个区间的,那么就是平衡树板子题。现在既然是放在子区间上的,那么套一个线段树就好啦~

    #include <bits/stdc++.h>
    using namespace std;
    
    const int N = 50000 + 5;
    const int INF = 1e8 + 5;
    
    #define ls (p << 1)
    #define rs (p << 1 | 1)
    #define mid ((l + r) >> 1)
    
    
    int n, m, tot, arr[N];
    
    struct FHQ_Node {
    	int w, lc, rc, sz, rd;
    }t[N << 8];
    
    struct FHQ_Treap {
    	
    	int rt;
    	
    	int NewNode (int w) {
    		t[++tot] = FHQ_Node {w, 0, 0, 1, rand ()};
    		return tot;
    	}
    	
    	void push_up (int p) {
    		t[p].sz = 1;
    		if (t[p].lc) t[p].sz += t[t[p].lc].sz;
    		if (t[p].rc) t[p].sz += t[t[p].rc].sz;
    	}
    	
    	void split (int now, int &A, int &B, int w) {
    		if (now == 0) {
    			A = B = 0; return;
    		}
    		if (t[now].w <= w) {
    			A = now; split (t[now].rc, t[A].rc, B, w);
    		} else {
    			B = now; split (t[now].lc, A, t[B].lc, w);
    		}
    		push_up (now);
    	}
    	
    	int merge (int A, int B) {
    		if (A * B == 0) {
    			return A + B;
    		}
    		if (t[A].rd < t[B].rd) {
    			t[A].rc = merge (t[A].rc, B); 
    			push_up (A); return A;
    		} else {
    			t[B].lc = merge (A, t[B].lc);
    			push_up (B); return B;
    		}
    	}
    	
    	int x, y, z;
    	
    	void Insert (int w) {
    		split (rt, x, y, w);
    		rt = merge (x, merge (NewNode (w), y));
    //		cout << "rt = " << rt << endl;
    	}
    	
    	void Delete (int w) {
    		split (rt, x, y, w - 1);
    		split (y, y, z, w);
    		y = merge (t[y].lc, t[y].rc);
    		rt = merge (x, merge (y, z));
    	}
    	
    	int pre (int w) {
    		split (rt, x, y, w - 1);
    		int p = x;
    		if (p == 0) {
    			return -0x7fffffff;
    		}
    		while (t[p].rc != 0) {
    			p = t[p].rc;
    		}
    		rt = merge (x, y);
    		return t[p].w;
    	}
    	
    	int nxt (int w) {
    		split (rt, x, y, w);
    		int p = y;
    		if (p == 0) {
    			return +0x7fffffff;
    		}
    		while (t[p].lc != 0) {
    			p = t[p].lc;
    		}
    		rt = merge (x, y);
    		return t[p].w;
    	}
    	
    	void print (int p) {
    		if (t[p].lc) print (t[p].lc);
    //		cout << "p = " << p << " w = " << t[p].w << " sz = " << t[p].sz << endl;
    		if (t[p].rc) print (t[p].rc);
    	}
    	
    	int rank (int w) {
    		split (rt, x, y, w - 1);
    		int ret = t[x].sz + 1;
    		rt = merge (x, y); 
    //		print (rt); cout << endl;
    		return ret;
    	}
    };
    
    struct Segment_Tree {
    	
    	FHQ_Treap tree[N << 2];
    	
    	void modify (int pos, int wpre, int wnew, int l = 1, int r = n, int p = 1) {
    //		cout << "p = " << p << endl;
    		if (wpre != -1) {tree[p].Delete (wpre);/*cout << "tree[" << p << "].Delete (" << wpre << ");" << endl;*/}
    		if (wnew != -1) {tree[p].Insert (wnew);/*cout << "tree[" << p << "].Insert (" << wnew << ");" << endl;*/}
    		if (l == r) return;
    		if (pos <= mid) {
    			modify (pos, wpre, wnew, l, mid + 0, ls);
    		} else {
    			modify (pos, wpre, wnew, mid + 1, r, rs);
    		}
    	}
    	
    	int tot, sta[N];
    	
    	void get_segment (int nl, int nr, int l = 1, int r = n, int p = 1) {
    		if (p == 1) tot = 0;
    		if (nl <= l && r <= nr) {
    			sta[++tot] = p; return;
    		}
    		if (nl <= mid) get_segment (nl, nr, l, mid + 0, ls);
    		if (mid < nr) get_segment (nl, nr, mid + 1, r, rs);
    	} 
    	
    	int rank (int l, int r, int w) {
    		get_segment (l, r);
    		int ret = 1;
    		for (int i = 1; i <= tot; ++i) {
    //			cout << tree[sta[i]].rank (w) << endl;
    			ret += (tree[sta[i]].rank (w) - 1);
    		}
    //		cout << "val = " << w << " rank = " << ret << endl;
    		return ret;
    	} 
    	
    	int kth (int l, int r, int k) {
    		int lval = 0, rval = INF;
    //		cout << "k = " << k << endl;
    		while (lval < rval) {
    //			getchar ();
    			int _mid = (lval + rval + 1) >> 1;
    //			cout << "lval = " << lval << " rval = " << rval << " mid = " << _mid << " rank " << k << " = " << rank (l, r, _mid) << endl;
    			if (rank (l, r, _mid) <= k) {
    				lval = _mid;
    			} else {
    				rval = _mid - 1;
    			}
    		}
    		return lval;
    	}
    	
    	int pre (int l, int r, int w) {
    		get_segment (l, r);
    		int maxw = -0x7fffffff;
    		for (int i = 1; i <= tot; ++i) {
    			maxw = max (maxw, tree[sta[i]].pre (w));
    		}
    		return maxw;
    	}
    	
    	int nxt (int l, int r, int w) {
    		get_segment (l, r);
    		int minw = +0x7fffffff;
    		for (int i = 1; i <= tot; ++i) {
    			minw = min (minw, tree[sta[i]].nxt (w));
    		}
    		return minw;
    	}
    }tr;
    
    int read () {
    	int s = 0, ch = getchar ();
    	while (!isdigit (ch)) {
    		ch = getchar ();
    	}
    	while (isdigit (ch)) {
    		s = s * 10 + ch - '0';
    		ch = getchar ();
    	}
    	return s;
    }
    
    int main () {
    //	freopen ("data.in", "r", stdin);
    	srand (time (NULL));
    	n = read (), m = read ();
    	for (int i = 1; i <= n; ++i) {
    		int w = read ();
    		tr.modify (i, -1, w);
    		arr[i] = w;
    //		cout << endl;
    	}
    	int opt, pos, l, r, k;
    	for (int i = 1; i <= m; ++i) {
    		opt = read ();
    		if (opt == 1) {
    			l = read (), r = read (), k = read ();
    			cout << tr.rank (l, r, k) << endl;
    		}
    		if (opt == 2) {
    			l = read (), r = read (), k = read ();
    			cout << tr.kth (l, r, k) << endl;
    		}	
    		if (opt == 3) {
    			pos = read (), k = read ();
    			tr.modify (pos, arr[pos], k);
    			arr[pos] = k;
    		} 
    		if (opt == 4) {
    			l = read (), r = read (), k = read ();
    			cout << tr.pre (l, r, k) << endl;
    		}
    		if (opt == 5) {
    			l = read (), r = read (), k = read ();
    			cout << tr.nxt (l, r, k) << endl;
    		}
    	}
    }
    
  • 相关阅读:
    [转]调试winlogon
    [转]整理一份我对Windows文件系统过滤驱动的sFilter工程代码的详细说明
    [转]在内核调试会话中设置用户态断点
    用Windbg调试GINA
    [转]文件过滤驱动开发
    [转]NDIS中间层驱动开发在Win7系统下和Windows XP系统下的区别
    [转]windbg下在kd模式也可以调试用户模式程序
    ProgressDialog多了一个外边框
    Dx trouble processing "java/nio/CharBuffer.class":
    ImageView图片重叠问题
  • 原文地址:https://www.cnblogs.com/maomao9173/p/10950396.html
Copyright © 2011-2022 走看看