• [HDU5799]This world need more Zhu


    题面戳我
    题意:
    给定一棵树,m次操作,每次询问某一棵子树中,或者是某一条路径上,出现次数为a的所有数字之和与出现次数为b的所有数字之和的gcd
    原题表述:the (gcd) of the sum of numbers that appears (a) times and the sum of numbers that appears (b) times in subtree (u) or on the path from (u) to (v) .

    sol

    你把题目看懂了就会发现这是一道莫队傻逼题
    首先输入的数据需要离散化
    把子树的询问和路径的询问分开处理,然后子树询问可以直接转化为序列莫队。
    路径询问就树上莫队即可。

    code

    记得多组数据初始化
    树链剖分中只有son数组要初始化
    莫队需要用到的所有数组都要初始化

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    #define ll long long
    const int N = 100005;
    int gi()
    {
    	int x=0,w=1;char ch=getchar();
    	while ((ch<'0'||ch>'9')&&ch!='-') ch=getchar();
    	if (ch=='-') w=0,ch=getchar();
    	while (ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
    	return w?x:-x;
    }
    struct edge{int to,next;}a[N<<1];
    int T,n,len,block,BL,m,col[N],o[N],head[N],cnt;
    int fa[N],dep[N],sz[N],son[N],top[N],dfn[N],low[N],ref[N];
    int ccnt,bl[N],s[N],tp;
    int cnt1,cnt2,vis[N],tot[N];ll sum[N],ans[N];
    struct query1{
    	int l,r,a,b,id;
    	bool operator < (const query1 &b) const
    		{
    			if (l/BL==b.l/BL) return r<b.r;
    			return l/BL<b.l/BL;
    		}
    }q1[N];
    struct query2{
    	int u,v,a,b,id;
    	bool operator < (const query2 &b) const
    		{
    			if (bl[u]==bl[b.u]) return bl[v]<bl[b.v];
    			return bl[u]<bl[b.u];
    		}
    }q2[N];
    void dfs1(int u,int f)
    {
    	fa[u]=f;dep[u]=dep[f]+1;sz[u]=1;
    	for (int e=head[u];e;e=a[e].next)
    	{
    		int v=a[e].to;if (v==f) continue;
    		dfs1(v,u);
    		sz[u]+=sz[v];if (sz[v]>sz[son[u]]) son[u]=v;
    	}
    }
    void dfs2(int u,int up)
    {
    	top[u]=up;dfn[u]=++cnt;ref[cnt]=u;int ttp=tp;
    	if (son[u]) dfs2(son[u],up);
    	if (tp-ttp>=block) {++ccnt;while (tp>ttp) bl[s[tp--]]=ccnt;}
    	for (int e=head[u];e;e=a[e].next)
    	{
    		int v=a[e].to;if (v==fa[u]||v==son[u]) continue;
    		dfs2(v,v);
    		if (tp-ttp>=block) {++ccnt;while (tp>ttp) bl[s[tp--]]=ccnt;}
    	}
    	low[u]=cnt;s[++tp]=u;
    }
    int lca(int u,int v)
    {
    	while (top[u]^top[v])
    	{
    		if (dep[top[u]]<dep[top[v]]) swap(u,v);
    		u=fa[top[u]];
    	}
    	return dep[u]<dep[v]?u:v;
    }
    void update(int x)
    {
    	if (!vis[x])
    	{
    		vis[x]=1;
    		sum[tot[col[x]]]-=o[col[x]];
    		tot[col[x]]++;
    		sum[tot[col[x]]]+=o[col[x]];
    	}
    	else
    	{
    		vis[x]=0;
    		sum[tot[col[x]]]-=o[col[x]];
    		tot[col[x]]--;
    		sum[tot[col[x]]]+=o[col[x]];
    	}
    }
    void change(int u,int v)
    {
    	while (u^v)
    		if (dep[u]>dep[v]) update(u),u=fa[u];
    		else update(v),v=fa[v];
    }
    ll Gcd(ll A,ll B){return B?Gcd(B,A%B):A;}
    int main()
    {
    	T=gi();
    	for (int zsy=1;zsy<=T;zsy++)
    	{
    		printf("Case #%d:
    ",zsy);
    		n=gi();m=gi();block=pow(n,0.6);BL=pow(n,0.5);
    		for (int i=1;i<=n;i++) col[i]=o[i]=gi();
    		sort(o+1,o+n+1);len=unique(o+1,o+n+1)-o-1;
    		for (int i=1;i<=n;i++) col[i]=lower_bound(o+1,o+len+1,col[i])-o;
    		memset(head,0,sizeof(head));cnt=ccnt=0;
    		memset(son,0,sizeof(son));
    		for (int i=1,u,v;i<n;i++)
    		{
    			u=gi();v=gi();
    			a[++cnt]=(edge){v,head[u]};head[u]=cnt;
    			a[++cnt]=(edge){u,head[v]};head[v]=cnt;
    		}
    		dfs1(1,0);cnt=0;dfs2(1,1);
    		while (tp) bl[s[tp--]]=ccnt;
    		cnt1=cnt2=0;
    		for (int i=1,opt,u,v,A,B;i<=m;i++)
    		{
    			opt=gi();u=gi();v=gi();A=gi();B=gi();
    			if (dfn[u]>dfn[v]) swap(u,v);
    			if (opt==1) q1[++cnt1]=(query1){dfn[u],low[u],A,B,i};
    			else q2[++cnt2]=(query2){u,v,A,B,i};
    		}
    		sort(q1+1,q1+cnt1+1);sort(q2+1,q2+cnt2+1);
    		int L=1,R=0;
    		memset(tot,0,sizeof(tot));
    		memset(sum,0,sizeof(sum));
    		memset(vis,0,sizeof(vis));
    		for (int i=1;i<=cnt1;i++)
    		{
    			while (L>q1[i].l) L--,update(ref[L]);
    			while (R<q1[i].r) R++,update(ref[R]);
    			while (L<q1[i].l) update(ref[L]),L++;
    			while (R>q1[i].r) update(ref[R]),R--;
    			ans[q1[i].id]=Gcd(sum[q1[i].a],sum[q1[i].b]);
    		}
    		memset(tot,0,sizeof(tot));
    		memset(sum,0,sizeof(sum));
    		memset(vis,0,sizeof(vis));
    		change(q2[1].u,q2[1].v);
    		int gg=lca(q2[1].u,q2[1].v);
    		update(gg);ans[q2[1].id]=Gcd(sum[q2[1].a],sum[q2[1].b]);update(gg);
    		for (int i=2;i<=cnt2;i++)
    		{
    			change(q2[i].u,q2[i-1].u);change(q2[i].v,q2[i-1].v);
    			gg=lca(q2[i].u,q2[i].v);
    			update(gg);ans[q2[i].id]=Gcd(sum[q2[i].a],sum[q2[i].b]);update(gg);
    		}
    		for (int i=1;i<=m;i++) printf("%lld
    ",ans[i]);
    	}
    	return 0;
    }
    
  • 相关阅读:
    Mongo DB intro
    java class 初始化
    Java Multi-Thread
    Java Exception
    PHP基础2
    Java STL
    javascript getElemet 获取元素 (转)
    javascript 异常处理
    javascript 输出
    LinkButton跳转页面及传递参数(转载)
  • 原文地址:https://www.cnblogs.com/zhoushuyu/p/8318491.html
Copyright © 2020-2023  润新知