• [做题记录-数据结构] [Ynoi2008] rdCcot


    考虑对于每个连通块维护代表元。但是同一深度会有多个代表元, 我们取(bfs)序靠前的一个维护。
    那么现在给出的结论是一个点是代表元当且仅当它与(bfs)序比它小的点没有连边
    那么现在就是要求一个(pre_i)表示最大的(i)使得(i < j)(b_i < b_j)(dis(i, j) leq C)。第三个限制可以点分治, 然后平衡树上二分得到区间。(b_i < b_j)可以把点排序以后按顺序插入平衡树, (i < j)也可以在二分之前直接从平衡树上(split)下来。
    注意点分治的时候(findrt)要进行两次!!!

    #include <bits/stdc++.h>
    #include <bits/extc++.h>
    
    using namespace std;
    using namespace __gnu_cxx;
    using namespace __gnu_pbds;
    
    class Input {
    	#define MX 1000000
    	private :
    		char buf[MX], *p1 = buf, *p2 = buf;
    		inline char gc() {
    			if(p1 == p2) p2 = (p1 = buf) + fread(buf, 1, MX, stdin);
    			return p1 == p2 ? EOF : *(p1 ++);
    		}
    	public :
    		Input() {
    			#ifdef Open_File
    				freopen("a.in", "r", stdin);
    				freopen("a.out", "w", stdout);
    			#endif
    		}
    		template <typename T>
    		inline Input& operator >>(T &x) {
    			x = 0; int f = 1; char a = gc();
    			for(; ! isdigit(a); a = gc()) if(a == '-') f = -1;
    			for(; isdigit(a); a = gc()) 
    				x = x * 10 + a - '0';
    			x *= f;
    			return *this;
    		}
    		inline Input& operator >>(char &ch) {
    			while(1) {
    				ch = gc();
    				if(ch != '
    ' && ch != ' ') return *this;
    			}
    		}
    		inline Input& operator >>(char *s) {
    			int p = 0;
    			while(1) {
    				s[p] = gc();
    				if(s[p] == '
    ' || s[p] == ' ' || s[p] == EOF) break;
    				p ++; 
    			}
    			s[p] = '';
    			return *this;
    		}
    	#undef MX
    } Fin;
    
    class Output {
    	#define MX 1000000
    	private :
    		char ouf[MX], *p1 = ouf, *p2 = ouf;
    		char Of[105], *o1 = Of, *o2 = Of;
    		void flush() { fwrite(ouf, 1, p2 - p1, stdout); p2 = p1; }
    		inline void pc(char ch) {
    			* (p2 ++) = ch;
    			if(p2 == p1 + MX) flush();
    		}
    	public :
    		template <typename T> 
    		inline Output& operator << (T n) {
    			if(n < 0) pc('-'), n = -n;
    			if(n == 0) pc('0');
    			while(n) *(o1 ++) = (n % 10) ^ 48, n /= 10;
    			while(o1 != o2) pc(* (--o1));
    			return *this; 
    		}
    		inline Output & operator << (char ch) {
    			pc(ch); return *this; 
    		}
    		inline Output & operator <<(const char *ch) {
    			const char *p = ch;
    			while( *p != '' ) pc(* p ++);
    			return * this;
    		}
    		~Output() { flush(); } 
    	#undef MX
    } Fout;
    
    #define cin Fin
    #define cout Fout
    #define endl '
    '
    
    using LL = long long;
    
    inline int log2(unsigned int x);
    inline int popcount(unsigned x);
    inline int popcount(unsigned long long x);
    
    const int N = 3e5 + 10;
    const int INF = 0x3f3f3f3f;
    
    int n, m, C;
    struct edge {
    	int to, next;
    } e[N << 1];
    int cnt, head[N];
    void push(int x, int y) { e[++ cnt] = (edge) {y, head[x]}; head[x] = cnt; }
    
    static const long long kMul = 0x9ddfea08eb382d69ULL;
    long long Seed = 1145141919810;
    inline long long fingerPrint(long long x) {
    	return x *= kMul, x ^= x >> 47, x *= kMul, x ^= x >> 47, x *= kMul, x ^= x >> 47, x * kMul;
    }
    inline int frand(void) { return Seed += fingerPrint(Seed); }
    
    struct Node {
    	Node *ls, *rs;
    	int val, rnd, mndis, dis;
    	Node() {}
    	Node(int _val, int _dis) : val(_val), rnd(frand()), ls(NULL), rs(NULL), mndis(_dis), dis(_dis) {}
    	void upd() {
    		mndis = dis;
    		if(ls) mndis = min(mndis, ls -> mndis); if(rs) mndis = min(mndis, rs -> mndis);
    	}
    	void print() {
    		if(ls) ls -> print();
    		cerr << val << ' ';
    		if(rs) rs -> print();
    	}
    } ;
    
    Node pool[1000000];
    Node *oo = pool;
    
    Node *NewNode(int val, int d) {
    	oo ++;
    	* oo = Node(val, d);
    	return oo;
    }
    
    class FhqTreap {
    	private :
    		Node *root;
    		Node *merge(Node *x, Node *y) {
    			if(x == NULL) return y;
    			if(y == NULL) return x;
    			if(x -> rnd <= y -> rnd) {
    				x -> rs = merge(x -> rs, y);
    				x -> upd(); return x;
    			}
    			else {
    				y -> ls = merge(x, y -> ls);
    				y -> upd(); return y;
    			}
    		}
    		void split(Node *now, int k, Node *&x, Node *&y) {
    			if(now == NULL) { x = NULL; y = NULL; return ; }
    			if(now -> val <= k) {
    				x = now;
    				split(now -> rs, k, x -> rs, y);
    			}
    			else {
    				y = now;
    				split(now -> ls, k, x, y -> ls);
    			}
    			now -> upd();
    		}
    	public :
    		FhqTreap() : root(NULL) { oo = pool; } 
    		void Clear() {
    			root = NULL; oo = pool;
    		}
    		void Insert(int k, int dis) {
    			Node *a = NULL, *b = NULL, *c = NULL;
    			split(root, k, a, b);
    			c = NewNode(k, dis);
    			root = merge(a, merge(c, b));
    		}
    		pair<int, int> qry(int i, int d) {
    			d = C - d;
    			Node *x = NULL, *y = NULL, *a = NULL, *b = NULL;
    			split(root, i, x, y); a = x; b = y; 
    			int res1 = 0;
    			if(x != NULL && x -> mndis <= d) {
    				while(x != NULL) {
    					if(x -> rs != NULL) {
    						if(x -> rs -> mndis <= d) {
    							x = x -> rs;
    							continue;
    						} 
    					}
    					if(x -> dis <= d) {
    						res1 = x -> val; break;
    					}
    					x = x -> ls;
    				}
    			}
    			int res2 = n + 1;
    			if(y != NULL && y -> mndis <= d) {
    				while(y != NULL) {
    					if(y -> ls != NULL) {
    						if(y -> ls -> mndis <= d) {
    							y = y -> ls;
    							continue;
    						} 
    					}
    					if(y -> dis <= d) {
    						res2 = y -> val; break;
    					}
    					y = y -> rs;
    				}
    			}
    			root = merge(a, merge(NewNode(i, C - d), b));
    			return make_pair(res1, res2);
    		}
    		void print() {
    			if(root != NULL) root -> print();
    		}
    } Treap;
    
    struct Bit {
    	int c[N];
    	#define lowbit(x) (x & -x)
    	void upd(int x, int y) {
    		for(; x <= n; x += lowbit(x)) c[x] += y;
    	}
    	void add(int l, int r, int v) {
    		upd(l, v); upd(r + 1, -v);
    	}
    	int ask(int x) {
    		int ans = 0;
    		for(; x; x -= lowbit(x)) ans += c[x];
    		return ans;
    	}
    } bit;
    
    int rt, sz[N], all, vis[N];
    
    void findrt(int x, int fx) {
    	sz[x] = 1;
    	int mx = 0;
    	for(int i = head[x]; i; i = e[i].next) {
    		int y = e[i].to;
    		if(y != fx && ! vis[y]) {
    			findrt(y, x);
    			sz[x] += sz[y];
    			mx = max(mx, sz[y]);
    		}
    	}
    	mx = max(mx, all - sz[x]);
    	if(mx * 2 <= all || rt == 0) rt = x;
    }
    
    int pre[N], suf[N], bfn[N], fa[N], dist[N];
    
    void getnode(int x, int fx, int nrt, int *tac, int dis) {
    	dist[x] = dis;
    	if(dis <= C) tac[++ tac[0]] = x;
    	else return ;
    	for(int i = head[x]; i; i = e[i].next) {
    		int y = e[i].to;
    		if(! vis[y] && y != fx) getnode(y, x, nrt, tac, dis + 1);
    	}
    }
    
    void calc(int x) {
    	static int tac[N];
    	tac[0] = 0;
    	getnode(x, 0, x, tac, 0);
    	sort(tac + 1, tac + 1 + tac[0], [](int a, int b) { return bfn[a] < bfn[b]; } );
    	Treap.Clear();
    	for(int p = 1; p <= tac[0]; p ++) {
    		int i = tac[p]; int d = dist[i];
    		pair<int, int> Get = Treap.qry(i, d);
    		pre[i] = max(pre[i], Get.first);
    		suf[i] = min(suf[i], Get.second);
    	}
    }
    
    void solve(int x) {
    	vis[x] = 1;
    	calc(x);
    	for(int i = head[x]; i; i = e[i].next) {
    		int y = e[i].to;
    		if(! vis[y]) {
    			findrt(y, 0);
    			all = sz[y]; rt = 0;
    			findrt(y, 0);
    			solve(rt);
    		}
    	}
    }
    
    struct Line { int l, r, v; };
    
    int Ans[N];
    vector<Line> mdf[N];
    vector<pair<int, int> > qry[N];
    
    void addmat(int l1, int r1, int l2, int r2) {
    	mdf[l1].push_back( {l2, r2, 1} );
    	mdf[r1 + 1].push_back( {l2, r2, -1} );
    }
    
    int main() {
    	cin >> n >> m >> C;
    	for(int i = 2, x; i <= n; i ++) {
    		cin >> x;
    		push(x, i); push(i, x);
    	}
    	deque<int> q;
    	q.push_back(1);
    	while(q.size()) {
    		int x = q.front(); q.pop_front();
    		bfn[x] = ++ bfn[0];
    		for(int i = head[x]; i; i = e[i].next) {
    			int y = e[i].to;
    			if(y != fa[x]) {
    				q.push_back(y);
    				fa[y] = x;
    			}
    		}
    	}
    	for(int i = 1; i <= n; i ++) pre[i] = 0, suf[i] = n + 1;
    	all = n; rt = 0;
    	findrt(1, 0);
    	findrt(rt, 0);
    	solve(rt);
    	for(int i = 1; i <= n; i ++) addmat(pre[i] + 1, i, i, suf[i] - 1);
    	for(int i = 1, l, r; i <= m; i ++) {
    		cin >> l >> r;
    		qry[l].push_back({r, i});
    	}
    	for(int i = 1; i <= n; i ++) {
    		for(auto p : mdf[i]) 
    			bit.add(p.l, p.r, p.v);
    		for(auto p : qry[i]) 
    			Ans[p.second] = bit.ask(p.first);
    	}
    	for(int i = 1; i <= m; i ++) cout << Ans[i] << endl;
    	return 0;
    }
    
    inline int log2(unsigned int x) { return __builtin_ffs(x); }
    inline int popcount(unsigned int x) { return __builtin_popcount(x); }
    inline int popcount(unsigned long long x) { return __builtin_popcountl(x); }
    
    // Last Year
    
  • 相关阅读:
    LeetCode-Minimum Path Sum
    LeetCode-Validate Binary Search Tree
    LeetCode-Recover Binary Search Tree
    LeetCode-Valid Parentheses
    LeetCode-Generate Parentheses
    LeetCode-4Sum
    BZOJ 2295: [POJ Challenge]我爱你啊
    BZOJ 2725: [Violet 6]故乡的梦
    BZOJ 3672: [Noi2014]购票
    BZOJ 4327:[JSOI2012]玄武密码
  • 原文地址:https://www.cnblogs.com/clover4/p/15263311.html
Copyright © 2020-2023  润新知