• bzoj4771 七彩树


    七彩树

    Time Limit: 5 Sec Memory Limit: 256 MB

    Description

    给定一棵n个点的有根树,编号依次为1到n,其中1号点是根节点。每个节点都被染上了某一种颜色,其中第i个节
    点的颜色为c[i]。如果c[i]=c[j],那么我们认为点i和点j拥有相同的颜色。定义depth[i]为i节点与根节点的距离
    ,为了方便起见,你可以认为树上相邻的两个点之间的距离为1。站在这棵色彩斑斓的树前面,你将面临m个问题。
    每个问题包含两个整数x和d,表示询问x子树里且depth不超过depth[x]+d的所有点中出现了多少种本质不同的颜色
    。请写一个程序,快速回答这些询问。

    Input

    第一行包含一个正整数T(1<=T<=500),表示测试数据的组数。
    每组数据中,第一行包含两个正整数n(1<=n<=100000)和m(1<=m<=100000),表示节点数和询问数。
    第二行包含n个正整数,其中第i个数为ci,分别表示每个节点的颜色。
    第三行包含n-1个正整数,其中第i个数为fi+1,表示节点i+1的父亲节点的编号。
    接下来m行,每行两个整数x(1<=x<=n)和d(0<=d<n),依次表示每个询问。
    输入数据经过了加密,对于每个询问,如果你读入了x和d,那么真实的x和d分别是x xor last和d xor last,
    其中last表示这组数据中上一次询问的答案,如果这是当前数据的第一组询问,那么last=0。
    输入数据保证n和m的总和不超过500000。

    Output

    对于每个询问输出一行一个整数,即答案。

    Sample Input

    1
    5 8
    1 3 3 2 2
    1 1 3 3
    1 0
    0 0
    3 0
    1 3
    2 1
    2 0
    6 2
    4 1

    Sample Output

    1
    2
    3
    1
    1
    2
    1
    1






    本来是个离线题的,就是说你按深度插入每个点。(当然要先树剖一下啦!)
    单独维护每一个颜色,两个相邻的点就在lca的地方减一就好了。
    但是他是个在线就的很毒。。。
    我们以毒攻毒,用可持久化线段树。。。

    
    #include<bits/stdc++.h>
    using namespace std;
    const int maxn = 1e5 + 5;
    struct lpl{
    	int fa, dfn, top, son, size, deep;
    }a[maxn];
    struct ld{
    	int id, dfn;
    	inline bool operator < (const ld &A)const{return dfn < A.dfn;}
    };
    struct lpd{
    	int sum, ls, rs;
    }node[10000010];
    int n, m, c[maxn];
    int lastans, last, num, tot, opt, cnt, mxd, root = 1;
    int d[maxn], rt[maxn * 5], ot[maxn], dp[maxn];
    vector<int> point[maxn];
    set<ld> s[maxn];
    set<ld>::iterator iter, op, ed;
    queue<int> q;
    
    namespace HLD{
    	void dfs1(int t, int fa){
    		a[t].size = 1; int tmp = 0; mxd = max(mxd, a[t].deep);
    		for(int i = point[t].size() - 1; i >= 0; --i){
    			int now = point[t][i]; if(now == fa) continue;
    			a[now].deep = a[t].deep + 1; dfs1(now, t);
    			a[t].size += a[now].size; 
    			if(tmp < a[now].size){tmp = a[now].size; a[t].son = now;}
    		}
    	}
    	
    	void dfs2(int t, int fa){
    		a[t].dfn = ++num;
    		if(a[t].son){a[a[t].son].top = a[t].top; dfs2(a[t].son, t);}
    		for(int i = point[t].size() - 1; i >= 0; --i){
    			int now = point[t][i]; if(now == fa || now == a[t].son) continue;
    			a[now].top = now; dfs2(now, t);
    		}
    	}
    	
    	inline int LCA(int x1, int x2){
    		if(a[a[x1].top].deep < a[a[x2].top].deep) swap(x1, x2);
    		while(a[x1].top != a[x2].top){
    			x1 = a[a[x1].top].fa; 
    			if(a[a[x1].top].deep < a[a[x2].top].deep) swap(x1, x2);
    		}
    		return (a[x1].deep > a[x2].deep) ? x2 : x1;
    	}
    }
    
    namespace SGT{
    	inline void update(int t){node[t].sum = node[node[t].ls].sum + node[node[t].rs].sum;}
    	
    	void build(int &t, int l, int r){
    		t = ++cnt; node[t].sum = 0; if(l == r) return;
    		int mid = (l + r) >> 1;
    		build(node[t].ls, l, mid); build(node[t].rs, mid + 1, r);
    	}
    	
    	void Modify(int &t, int l, int r, int pos, int val){
    		t = ++cnt; node[t] = node[last];
    		if(l == r){node[t].sum += val; return;}
    		int mid = (l + r) >> 1;
    		if(pos <= mid){last = node[last].ls; Modify(node[t].ls, l, mid, pos, val);}
    		else{last = node[last].rs; Modify(node[t].rs, mid + 1, r, pos, val);}
    		update(t);
    	}
    	
    	int Query(int t, int l, int r, int ql, int qr){
    		if(l == ql && r == qr) return node[t].sum;
    		int mid = (l + r) >> 1;
    		if(qr <= mid) return Query(node[t].ls, l, mid, ql, qr);
    		if(mid < ql) return Query(node[t].rs, mid + 1, r, ql, qr);
    		return Query(node[t].ls, l, mid, ql, mid) + Query(node[t].rs, mid + 1, r, mid + 1, qr);
    	}
    }
    
    template<typename T>
    inline void read(T &x){
    	x = 0; static char c = getchar();
    	while(!isdigit(c)) c = getchar();
    	while(isdigit(c)){x = x * 10 + c - '0'; c = getchar();}
    }
    
    template<typename T>
    void write(T x){
    	if(x / 10) write(x / 10);
    	putchar(x % 10 + '0');
    }
    
    inline void putit(){
    	read(n); read(m); lastans = 0; mxd = 0;
    	for(int i = 1; i <= n; ++i) {
    		point[i].clear(); s[i].clear(); 
    		a[i].son = 0; read(c[i]);
    	}
    	for(int f, i = 1; i < n; ++i){
    		read(f); a[i + 1].fa = f; 
    		point[f].push_back(i + 1);
    	}
    }
    
    inline void prepare(){
    	a[root].deep = 1; num = 0; memset(rt, 0, sizeof(rt));
    	HLD::dfs1(root, 0); a[1].top = 1; HLD::dfs2(root, 0);
    	q.push(root); int now; tot = 0;
    	while(!q.empty()){
    		now = q.front(); q.pop(); d[++tot] = now; 
    		for(int i = point[now].size() - 1; i >= 0; --i) q.push(point[now][i]);
    	}
    	cnt = 0; SGT::build(rt[0], 1, n); opt = 0;
    	bool qian, hou;
    	for(int color, i = 1; i <= tot; ++i){
    		color = c[d[i]];
    		iter = s[color].insert((ld){d[i], a[d[i]].dfn}).first;
    		qian = (iter != s[color].begin()); iter++; hou = (iter != s[color].end()); iter--;
    		if(qian){iter--; op = iter; iter++;}
    		if(hou){iter++; ed = iter; iter--;} 
    		if(qian && hou){
    			last = rt[opt]; 
    			SGT::Modify(rt[++opt], 1, n, a[HLD::LCA(op -> id, ed -> id)].dfn, 1);
    		}
    		if(qian){
    			last = rt[opt];
    			SGT::Modify(rt[++opt], 1, n, a[HLD::LCA(op -> id, iter -> id)].dfn, -1);	
    		}
    		if(hou){
    			last = rt[opt];
    			SGT::Modify(rt[++opt], 1, n, a[HLD::LCA(iter -> id, ed -> id)].dfn, -1);	
    		}
    		last = rt[opt]; SGT::Modify(rt[++opt], 1, n, iter -> dfn, 1);
    		ot[d[i]] = opt; dp[a[d[i]].deep] = d[i];
    	}
    }
    
    inline void workk(){
    	int x, D;
    	while(m--){
    		read(x); read(D); 
    		x ^= lastans; D ^= lastans;
    		D += a[x].deep; D = min(D, mxd);
    		D = ot[dp[D]];
    		lastans = SGT::Query(rt[D], 1, n, a[x].dfn, a[x].dfn + a[x].size - 1);
    		write(lastans); putchar(10);
    	}
    }
    
    int main()
    {
    	int T; read(T);	
    	while(T--){
    		putit();
    		prepare();
    		workk();		
    	} 
    	return 0;
    }
    
    
    心如花木,向阳而生。
  • 相关阅读:
    在java中请求webservice接口并且处理xml解析实现代码
    uniapp微信小程序唤起微信支付
    微信二维码图片添加资料
    uniapp支付宝App支付编写(沙箱支付)
    Java之xlsx文件上传到服务器
    echarts中国省份坐标数据
    kafka参数配置
    docker
    mysql 异步复制,半同步复制
    centos7安装mysql
  • 原文地址:https://www.cnblogs.com/LLppdd/p/9780186.html
Copyright © 2020-2023  润新知