zoukankan      html  css  js  c++  java
  • hdu5111 树链剖分,主席树

    hdu5111

    链接

    hdu

    思路

    先考虑序列上如何解决。

    1 3 2 5 4
    1 2 4 5 3
    

    这个序列变成

    1 2 3 4 5
    1 3 5 5 2
    

    是对答案没有影响的(显然)。
    然后查询操作(l,r,L,R)就是,
    一段连续的区间([L,R])内包含几个值在([l,r])的数字个数.
    主席树就可以做了。
    (query(rt[L-1],rt[R],[l,r]的和))
    可以用树链剖分把树上问题转化成链上。
    左边一棵树树链剖分,每一条链子都是一段连续的。
    右边一棵树根据父子关系建立主席树。
    然后向上跳统计贡献。

    吐槽

    本来我写完之后可以两遍编译,一遍样例,一遍AC的。
    鬼知道我清空出了什么毛病。

    for(i 0 to limit-1) a[i]=0
    

    居然清空不了。
    debug了半天,换成了memset才过。
    我也是醉了。

    代码

    #include <iostream>
    #include <map>
    #include <cstring>
    #include <algorithm>
    #define ls(x) (t[x].ls)
    #define rs(x) (t[x].rs)
    using namespace std;
    const int _=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 n1,n2,w1[_],w2[_],rt[_];
    map<int,int> dsr;
    struct node {
    	int v,nxt;
    }e1[_<<1],e2[_<<1];
    int head1[_],head2[_],tot1,tot2;
    void add1(int u,int v) {
    	e1[++tot1].v=v;
    	e1[tot1].nxt=head1[u];
    	head1[u]=tot1;
    }
    void add2(int u,int v) {
    	e2[++tot2].v=v;
    	e2[tot2].nxt=head2[u];
    	head2[u]=tot2;
    }
    namespace ZXS {
    	struct node {
    		int ls,rs,tot;
    	}t[_*30];
    	int cnt;
    	void clear() {
    		memset(t,0,sizeof(t));
    		// for(int i=0;i<=cnt;++i)
    		// 	ls(i)=rs(i)=t[i].tot=0;
    		cnt=0;
    	}
    	void insert(int l,int r,int k,int x,int &y) {
    		t[y=++cnt]=t[x];
    		t[y].tot++;
    		if(l==r) return;
    		int mid=(l+r)>>1;
    		if(k<=mid) insert(l,mid,k,ls(x),ls(y));
    		else insert(mid+1,r,k,rs(x),rs(y));
    	}
    	int query(int l,int r,int L,int R,int x,int y) {
    		if(L<=l&&r<=R) return t[y].tot-t[x].tot;
    		int mid=(l+r)>>1,ans=0;
    		if(L<=mid) ans+=query(l,mid,L,R,ls(x),ls(y));
    		if(R>mid) ans+=query(mid+1,r,L,R,rs(x),rs(y));
    		return ans;
    	}
    }
    namespace LCA{
    	int siz[_],son[_],top[_],f[_],dep[_],idx[_],cnt;
    	void clear() {
    		cnt=0;
    		memset(idx,0,sizeof(idx));
    		// memset(siz,0,sizeof(siz));
    		memset(son,0,sizeof(son));
    		// memset(top,0,sizeof(top));
    		// memset(dep,0,sizeof(dep));
    		// memset(f,0,sizeof(f));
    	}
    	void dfs1(int u,int fa) {
    		dep[u]=dep[fa]+1;
    		f[u]=fa;
    		siz[u]=1;
    		for(int i=head2[u];i;i=e2[i].nxt) {
    			int v=e2[i].v;
    			if(v==fa) continue;
    			dfs1(v,u);
    			siz[u]+=siz[v];
    			if(siz[v]>siz[son[u]]) son[u]=v;
    		}
    	}
    	void dfs2(int u,int topf) {
    		idx[u]=++cnt;
    		top[u]=topf;
    		if(!son[u]) return;
    		dfs2(son[u],topf);
    		for(int i=head2[u];i;i=e2[i].nxt) {
    			int v=e2[i].v;
    			if(!idx[v]) dfs2(v,v);
    		}
    	}
    	int query(int x,int y) {
    		while(top[x]!=top[y]) {
    	        if(dep[top[x]]<dep[top[y]]) swap(x,y);
    	        x=f[top[x]];
    	    }
    		if(dep[x]>dep[y]) swap(x,y);
    		return x;
    	}
    }
    namespace SLPF{
    	int siz[_],son[_],top[_],f[_],dep[_],idx[_],cnt;
    	void clear() {
    		cnt=0;
    		memset(idx,0,sizeof(idx));
    		// memset(siz,0,sizeof(siz));
    		memset(son,0,sizeof(son));
    		// memset(top,0,sizeof(top));
    		// memset(dep,0,sizeof(dep));
    		// memset(f,0,sizeof(f));
    	}
    	void dfs1(int u,int fa) {
    		dep[u]=dep[fa]+1;
    		f[u]=fa;
    		siz[u]=1;
    		for(int i=head1[u];i;i=e1[i].nxt) {
    			int v=e1[i].v;
    			if(v==fa) continue;
    			dfs1(v,u);
    			siz[u]+=siz[v];
    			if(siz[v]>siz[son[u]]) son[u]=v;
    		}
    	}
    	void dfs2(int u,int topf) {
    		idx[u]=++cnt;
    		dsr[w1[u]]=cnt;
    		top[u]=topf;
    		if(!son[u]) return;
    		dfs2(son[u],topf);
    		for(int i=head1[u];i;i=e1[i].nxt) {
    			int v=e1[i].v;
    			if(!idx[v]) dfs2(v,v);
    		}
    	}
    	void QQ(int x,int y,int u2,int v2) {
    		int lca=LCA::query(u2,v2),ans=0;
    		while(top[x]!=top[y]) {
    	        if(dep[top[x]]<dep[top[y]]) swap(x,y);
    			ans+=ZXS::query(1,n1,idx[top[x]],idx[x],rt[lca],rt[u2]);
    			// cout<<ZXS::query(1,n1,idx[top[x]],idx[x],rt[lca],rt[u2])<<"
    ";
    			ans+=ZXS::query(1,n1,idx[top[x]],idx[x],rt[LCA::f[lca]],rt[v2]);
    			// cout<<ZXS::query(1,n1,idx[top[x]],idx[x],rt[LCA::f[lca]],rt[v2])<<"
    ";
    	        x=f[top[x]];
    	    }
    	    if(dep[x]>dep[y]) swap(x,y);
    	    ans+=ZXS::query(1,n1,idx[x],idx[y],rt[lca],rt[u2]);
    	    // cout<<ZXS::query(1,n1,idx[x],idx[y],rt[lca],rt[u2])<<"
    ";
    		ans+=ZXS::query(1,n1,idx[x],idx[y],rt[LCA::f[lca]],rt[v2]);
    		// cout<<ZXS::query(1,n1,idx[x],idx[y],rt[LCA::f[lca]],rt[v2])<<"
    ";
    	    printf("%d
    ",ans);
    	}
    }
    void dfs(int u,int fa) {
    	if(dsr.count(w2[u])) ZXS::insert(1,n1,dsr[w2[u]],rt[fa],rt[u]);
    	else rt[u]=rt[fa];
    	for(int i=head2[u];i;i=e2[i].nxt) {
    		int v=e2[i].v;
    		if(v==fa) continue;
    		dfs(v,u);
    	}
    }
    int main() {
    	// freopen("data.in","r",stdin);
    	// freopen("a.out","w",stdout);
    	while(scanf("%d",&n1)!=EOF) {
    		//clear
    		LCA::clear();
    		SLPF::clear();
    		ZXS::clear();
    		dsr.clear();
    		tot1=tot2=0;
    		memset(rt,0,sizeof(rt));
    		memset(head1,0,sizeof(head1));
    		memset(head2,0,sizeof(head2));
    		//read
    		for(int i=2;i<=n1;++i) {
    			int u=i,v=read();
    //			cout<<u<<"->"<<v<<"
    ";
    			add1(u,v),add1(v,u);
    		}
    		for(int i=1;i<=n1;++i) w1[i]=read();
    		n2=read();
    		for(int i=2;i<=n2;++i) {
    			int u=i,v=read();
    //			cout<<u<<"->"<<v<<"
    ";
    			add2(u,v),add2(v,u);
    		}
    		for(int i=1;i<=n2;++i) w2[i]=read();
    		//init
    		SLPF::dfs1(1,0);
    		SLPF::dfs2(1,1);
    		LCA::dfs1(1,0);
    		LCA::dfs2(1,1);
    		dfs(1,0);
    		//ask
    		int Q=read();
    		while(Q --> 0) {
    			int u1=read(),v1=read(),u2=read(),v2=read();
    			SLPF::QQ(u1,v1,u2,v2);
    		}
    	}
    	return 0;
    }
    
    
  • 相关阅读:
    WPF复杂形状按钮
    (WPF)360安全卫士界面设计
    WPF图标拾取器
    WPF透明窗体制作
    空间分析开源库GEOS
    GIS开源程序收集
    flask 链接 url_for()
    自定制404错误页码
    Flask 模板语言
    flask路由和视图和cookie
  • 原文地址:https://www.cnblogs.com/dsrdsr/p/11389182.html
Copyright © 2011-2022 走看看