• luogu P2633 Count on a tree


    思路

    强制在线--主席树
    以1为root建主席树 (就是在树上建树,差不多)
    rt[i]就是1到i的路径上的一棵树的root
    其实我感觉,主席树之间的运算差不多于加减
    类似lca的运算
    root(1到x)+root(1到y)-root(lca)-root(fa[lca])
    查询他们的第k小就OK

    错误 or debug的地方

    错误:运算写错了,算是思路不清晰吧 、、、
    debug:和他xor的是原来的数,不是lsh之后的数字、、、

    代码

    #include <bits/stdc++.h>
    #define FOR(i,a,b) for(int i=a;i<=b;++i)
    using namespace std;
    const int maxn=1e5+7;
    int read() {
    	int x=0,f=1;char s=getchar();
    	for(;s>'9'||s<'0';s=getchar()) if(s=='-') f=-1;
    	for(;s>='0'&&s<='9';s=getchar()) x=x*10+s-'0';
    	return x*f;
    }
    int n,m,a[maxn],b[maxn];
    struct node {
    	int v,nxt;
    }e[maxn<<1];
    int head[maxn<<1],tot;
    void add_edge(int u,int v) {
    	e[++tot].v=v;
    	e[tot].nxt=head[u];
    	head[u]=tot;
    }
    namespace LCA {
    	int dep[maxn],st[maxn][21];
    	void dfs(int u,int f) {
    		for(int i=head[u];i;i=e[i].nxt) {
    			int v=e[i].v;
    			if(v==f) continue;
    			st[v][0]=u;
    			dep[v]=dep[u]+1;
    			dfs(v,u);
    		}
    	}
    	int Lca(int x,int y) {
    		if(dep[x]<dep[y]) swap(x,y);
    		for(int i=20;i>=0;--i)
    			if(dep[st[x][i]]>=dep[y]) x=st[x][i];
    		if(x==y) return x;
    		for(int i=20;i>=0;--i)
    			if(st[x][i]!=st[y][i]) x=st[x][i],y=st[y][i];
    		return st[x][0];
    	}
    	void init() {
    		dep[1]=1;
    		dfs(1,0);
    		FOR(j,1,20) FOR(i,1,n)
    			st[i][j]=st[st[i][j-1]][j-1]; 
    	}
    }
    using namespace LCA;
    struct edge {
    	int ch[2],siz;
    }t[maxn*30];
    int rt[maxn],cnt;
    void build(int &now,int old,int l,int r,int k) {
    	now=++cnt;
    	t[now]=t[old];
    	t[now].siz++;
    	if(l==r) return;
    	int mid=(l+r)>>1;
    	if(k<=mid) build(t[now].ch[0],t[old].ch[0],l,mid,k);
    	else build(t[now].ch[1],t[old].ch[1],mid+1,r,k);
    }
    void DFS(int u,int f) {
    	build(rt[u],rt[f],1,n,a[u]);
    	for(int i=head[u];i;i=e[i].nxt) {
    		int v=e[i].v;
    		if(v==f) continue;
    		DFS(v,u);
    	}
    }
    int query(int a,int b,int c,int d,int l,int r,int k) {
    	if(l==r) return l;
    	int tot=t[t[a].ch[0]].siz+t[t[b].ch[0]].siz-t[t[c].ch[0]].siz-t[t[d].ch[0]].siz;
    	int mid=(l+r)>>1;
    	if(tot>=k) return query(t[a].ch[0],t[b].ch[0],t[c].ch[0],t[d].ch[0],l,mid,k);
    	else return query(t[a].ch[1],t[b].ch[1],t[c].ch[1],t[d].ch[1],mid+1,r,k-tot);
    }
    int main() {
    	//@read
    	n=read(),m=read();
    	FOR(i,1,n) a[i]=b[i]=read();
    	FOR(i,2,n) {
    		int x=read(),y=read();
    		add_edge(x,y);
    		add_edge(y,x);
    	}
    	//@lsh
    	sort(b+1,b+1+n);
    	int len=unique(b+1,b+1+n)-b-1;
    	FOR(i,1,n) a[i]=lower_bound(b+1,b+1+len,a[i])-b;
    	//@lca_init
    	init();
    	//@build
    	DFS(1,0);
    	//@work
    	int lastans=0;
    	FOR(i,1,m) {
    		int u=read(),v=read(),k=read();
    		u=(u^lastans);
    		int lca=Lca(u,v);
    		lastans=b[query(rt[u],rt[v],rt[lca],rt[st[lca][0]],1,n,k)];
    		cout<<lastans<<"
    "; 
    	}
    	return 0;
    }
    
  • 相关阅读:
    MySql多表循环遍历更新
    GridView控件的选择功能,代码实现CheckBox控件的全选、反选以及取消
    使用HTTP POST请求12306网站接口查询火车车次API
    GridView控件的绑定分页功能
    使用HTTP GET请求12306网站接口获取车站名和车站Code
    浅谈从Oracle数据库中取出10条数据的Select语句与Sql Server、MySql的区别
    2022 程序员口语提升指南
    R语言与java整合
    新浪的股票接口 c# (收藏)
    摘记
  • 原文地址:https://www.cnblogs.com/dsrdsr/p/10107060.html
Copyright © 2020-2023  润新知