• 13th东北四省赛D.Master of Data Structure——暴力+虚树


    题目链接:

    D.Master of Data Structure

    题目大意:

    给一棵$n$个点的树,每个点有一个点权,初始为$0$,有$m$次操作。操作分为$7$种:

    1、路径加

    2、路径异或

    3、路径减

    4、求路径和

    5、求路径异或和

    6、求路径最大点权-最小点权

    7、求路径上点权与$k$差的绝对值的最小值

    所有操作都是路径操作,且操作只有$2000$次,那么有许多路径每次都会被一起修改或询问。将所有操作路径端点建虚树,记录虚树上相邻两点间的节点数,暴力完成操作即可。

    #include<set>
    #include<stack>
    #include<queue>
    #include<cmath>
    #include<vector>
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define ll long long
    using namespace std;
    int n,m,x,y,T;
    int st[500010];
    int top,tot;
    int s[500010];
    vector<int>v[500010];
    int head[500010];
    int to[500010];
    int nex[500010];
    int val[500010];
    int sum[500010];
    int w[500010];
    int d[500010];
    int dfn,cnt;
    int a[4010];
    int f[500010][20];
    int num[500010];
    struct query
    {
    	int opt,u,v,k;
    }q[2010];
    int init()
    {
    	dfn=top=cnt=tot=0;
    	for(int i=1;i<=n;i++)v[i].clear();
    	memset(s,0,sizeof(s));
    	memset(w,0,sizeof(w));
    	memset(d,0,sizeof(d));
    	memset(f,0,sizeof(f));
    	memset(st,0,sizeof(st));
    	memset(head,0,sizeof(head));
    	memset(to,0,sizeof(to));
    	memset(nex,0,sizeof(nex));
    	memset(val,0,sizeof(val));
    	memset(num,0,sizeof(num));
    	memset(sum,0,sizeof(sum));
    }
    bool cmp(int x,int y)
    {
    	return s[x]<s[y];
    }
    void add(int x,int y)
    {
    	nex[++tot]=head[x];
    	head[x]=tot;
    	to[tot]=y;
    	sum[tot]=d[y]-d[x]-1;
    }
    void dfs(int x,int fa)
    {
    	s[x]=++dfn;
    	d[x]=d[fa]+1;
    	f[x][0]=fa;
    	for(int i=1;i<=19;i++)f[x][i]=f[f[x][i-1]][i-1];
    	int size=v[x].size();
    	for(int i=0;i<size;i++)
    	{
    		if(v[x][i]!=fa)dfs(v[x][i],x);
    	}
    }
    int lca(int x,int y)
    {
    	if(d[x]<d[y])swap(x,y);
    	int dep=d[x]-d[y];
    	for(int i=0;i<=19;i++)
    	{
    		if((dep&(1<<i)))x=f[x][i];
    	}
    	if(x==y)return x;
    	for(int i=19;i>=0;i--)
    	{
    		if(f[x][i]!=f[y][i])x=f[x][i],y=f[y][i];
    	}
    	return f[x][0];
    }
    void insert(int x)
    {
    	int anc=lca(st[top],x);
    	while(top>1&&d[st[top-1]]>=d[anc])
    	{
    		add(st[top-1],st[top]);
    		top--;
    	}
    	if(anc!=st[top])
    	{
    		add(anc,st[top]);
    		st[top]=anc;
    	}
    	st[++top]=x;
    }
    void dfs2(int x,int fa)
    {
    	d[x]=d[fa]+1;
    	f[x][0]=fa;
    	for(int i=head[x];i;i=nex[i])
    	{
    		if(to[i]!=fa)
    		{
    			num[to[i]]=i;
    			dfs2(to[i],x);
    		}
    	}
    }
    void do1(int u,int v,int k)
    {
    	if(d[u]<d[v])swap(u,v);
    	while(d[u]>d[v])
    	{
    		w[u]+=k;
    		val[num[u]]+=k;		
    		u=f[u][0];
    	}
    	if(u==v)
    	{
    		w[u]+=k;
    		return ;
    	}
    	while(u!=v)
    	{
    		w[u]+=k,w[v]+=k;
    		val[num[u]]+=k,val[num[v]]+=k;
    		u=f[u][0],v=f[v][0];
    	}
    	w[u]+=k;
    }
    void do2(int u,int v,int k)
    {
    	if(d[u]<d[v])swap(u,v);
    	while(d[u]>d[v])
    	{
    		w[u]^=k;
    		val[num[u]]^=k;
    		u=f[u][0];
    	}
    	if(u==v)
    	{
    		w[u]^=k;
    		return ;
    	}
    	while(u!=v)
    	{
    		w[u]^=k,w[v]^=k;
    		val[num[u]]^=k,val[num[v]]^=k;
    		u=f[u][0],v=f[v][0];
    	}
    	w[u]^=k;
    }
    void do3(int u,int v,int k)
    {
    	if(d[u]<d[v])swap(u,v);
    	while(d[u]>d[v])
    	{
    		w[u]>=k?w[u]-=k:1;
    		val[num[u]]>=k?val[num[u]]-=k:1;
    		u=f[u][0];
    	}
    	if(u==v)
    	{
    		w[u]>=k?w[u]-=k:1;
    		return ;
    	}
    	while(u!=v)
    	{
    		w[u]>=k?w[u]-=k:1;
    		w[v]>=k?w[v]-=k:1;
    		val[num[u]]>=k?val[num[u]]-=k:1;
    		val[num[v]]>=k?val[num[v]]-=k:1;
    		u=f[u][0],v=f[v][0];
    	}
    	w[u]>=k?w[u]-=k:1;
    }
    void do4(int u,int v)
    {
    	ll ans=0;
    	if(d[u]<d[v])swap(u,v);
    	while(d[u]>d[v])
    	{
    		ans+=w[u];
    		ans+=1ll*val[num[u]]*sum[num[u]];
    		u=f[u][0];
    	}
    	if(u==v)
    	{
    		ans+=w[u];
    		printf("%lld
    ",ans);
    		return ;
    	}
    	while(u!=v)
    	{
    		ans+=w[u],ans+=w[v];
    		ans+=1ll*val[num[u]]*sum[num[u]];
    		ans+=1ll*val[num[v]]*sum[num[v]];
    		u=f[u][0],v=f[v][0];
    	}
    	ans+=w[u];
    	printf("%lld
    ",ans);
    	return ;
    }
    void do5(int u,int v)
    {
    	int ans=0;
    	if(d[u]<d[v])swap(u,v);
    	while(d[u]>d[v])
    	{
    		ans^=w[u];
    		ans^=(sum[num[u]]%2==0?0:val[num[u]]);
    		u=f[u][0];
    	}
    	if(u==v)
    	{
    		ans^=w[u];
    		printf("%d
    ",ans);
    		return ;
    	}
    	while(u!=v)
    	{
    		ans^=w[u],ans^=w[v];
    		ans^=(sum[num[u]]%2==0?0:val[num[u]]);
    		ans^=(sum[num[v]]%2==0?0:val[num[v]]);
    		u=f[u][0],v=f[v][0];
    	}
    	ans^=w[u];
    	printf("%d
    ",ans);
    	return ;
    }
    void do6(int u,int v)
    {
    	int mx,mn;
    	mx=0,mn=1<<30;
    	if(d[u]<d[v])swap(u,v);
    	while(d[u]>d[v])
    	{
    		mx=max(mx,w[u]),mn=min(mn,w[u]);
    		if(sum[num[u]])mx=max(mx,val[num[u]]),mn=min(mn,val[num[u]]);
    		u=f[u][0];
    	}
    	if(u==v)
    	{
    		mx=max(mx,w[u]),mn=min(mn,w[u]);
    		printf("%d
    ",mx-mn);
    		return ;
    	}
    	while(u!=v)
    	{
    		mx=max(mx,w[u]),mn=min(mn,w[u]);
    		mx=max(mx,w[v]),mn=min(mn,w[v]);
    		if(sum[num[u]])mx=max(mx,val[num[u]]),mn=min(mn,val[num[u]]);
    		if(sum[num[v]])mx=max(mx,val[num[v]]),mn=min(mn,val[num[v]]);
    		u=f[u][0],v=f[v][0];
    	}
    	mx=max(mx,w[u]),mn=min(mn,w[u]);
    	printf("%d
    ",mx-mn);
    	return ;
    }
    void do7(int u,int v,int k)
    {
    	int ans=1<<30;
    	if(d[u]<d[v])swap(u,v);
    	while(d[u]>d[v])
    	{
    		ans=min(ans,abs(w[u]-k));
    		if(sum[num[u]])ans=min(ans,abs(val[num[u]]-k));
    		u=f[u][0];
    	}
    	if(u==v)
    	{
    		ans=min(ans,abs(w[u]-k));
    		printf("%d
    ",ans);
    		return ;
    	}
    	while(u!=v)
    	{
    		ans=min(ans,abs(w[u]-k));
    		ans=min(ans,abs(w[v]-k));
    		if(sum[num[u]])ans=min(ans,abs(val[num[u]]-k));
    		if(sum[num[v]])ans=min(ans,abs(val[num[v]]-k));
    		u=f[u][0],v=f[v][0];
    	}
    	ans=min(ans,abs(w[u]-k));
    	printf("%d
    ",ans);
    	return ;
    }
    void work()
    {
    	for(int i=1;i<n;i++)
    	{
    		scanf("%d%d",&x,&y);
    		v[x].push_back(y);
    		v[y].push_back(x);
    	}
    	dfs(1,0);
    	for(int i=1;i<=m;i++)
    	{
    		scanf("%d%d%d",&q[i].opt,&q[i].u,&q[i].v);
    		if(q[i].opt<4||q[i].opt>6)scanf("%d",&q[i].k);
    		a[++cnt]=q[i].u,a[++cnt]=q[i].v;
    	}
    	sort(a+1,a+1+cnt,cmp);
    	if(a[1]!=1)
    	{
    		st[++top]=1;
    	}
    	for(int i=1;i<=cnt;i++)
    	{
    		if(a[i]==a[i-1])continue;
    		insert(a[i]);
    	}
    	while(top>1)
    	{
    		add(st[top-1],st[top]);
    		top--;
    	}
    	dfs2(1,0);
    	for(int i=1;i<=m;i++)
    	{
    		if(q[i].opt==1)do1(q[i].u,q[i].v,q[i].k);
    		else if(q[i].opt==2)do2(q[i].u,q[i].v,q[i].k);
    		else if(q[i].opt==3)do3(q[i].u,q[i].v,q[i].k);
    		else if(q[i].opt==4)do4(q[i].u,q[i].v);
    		else if(q[i].opt==5)do5(q[i].u,q[i].v);
    		else if(q[i].opt==6)do6(q[i].u,q[i].v);
    		else do7(q[i].u,q[i].v,q[i].k);
    	}
    }
    int main()
    {
    	scanf("%d",&T);
    	while(T--)
    	{
    		scanf("%d%d",&n,&m);
    		init();
    		work();
    	}
    }
  • 相关阅读:
    QWidget在QPopupMenu显示
    QTable中header高度
    在OpenSSL中添加自定义加密算法
    LibXML2不支持中文补遗
    基于arm+uClinux的嵌入式系统的开发
    关于嵌入式系统的启动
    在Qt/Embedded 2.3.8中添加MX21Ads键盘处理
    QT/Embedded 2.3.8 MX21ADS板移植
    Windows/Linux/Solaris 软中断处理机制
    RMI原理及实现
  • 原文地址:https://www.cnblogs.com/Khada-Jhin/p/14763943.html
Copyright © 2020-2023  润新知