联考20200523 T1 签到题





分析:
复杂到离谱的题面,真就硬是在转化模型呗(
数组末尾加一个INF
每个位置向第一次代替它的位置连边,连出一棵树
当x,y不是祖先后代关系时,最优公共对应点为LCA
否则是LCA的父亲(父亲为根时输出问号)
1号操作是自己和儿子节点加权,自己和重儿子暴力修改,轻儿子树链剖分时暴力查询,复杂度都是(log)可以接受
2号操作是查询路径权值和,简单维护
模型转换成功了之后就是一道简单数据结构

#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector>
#include<iostream>
#include<map>
#include<string>

#define maxn 200005
#define INF 0x3f3f3f3f

using namespace std;

inline long long getint()
{
	long long num=0,flag=1;char c;
	while((c=getchar())<'0'||c>'9')if(c=='-')flag=-1;
	while(c>='0'&&c<='9')num=num*10+c-48,c=getchar();
	return num*flag;
}

int n,m;
long long A[maxn],w[maxn],delta[maxn];
int fir[maxn],nxt[maxn],to[maxn],cnt;
int fa[maxn],tp[maxn],dpt[maxn],son[maxn],sz[maxn];
int pos[maxn],id[maxn],cur;
int stk[maxn],top;
long long sum[maxn<<2];

inline void newnode(int u,int v)
{to[++cnt]=v,nxt[cnt]=fir[u],fir[u]=cnt;}
inline void dfs1(int u)
{
	sz[u]=1;
	for(int i=fir[u];i;i=nxt[i])
	{
		fa[to[i]]=u,dpt[to[i]]=dpt[u]+1;
		dfs1(to[i]),sz[u]+=sz[to[i]];
		if(sz[son[u]]<sz[to[i]])son[u]=to[i];
	}
}

inline void dfs2(int u,int ac)
{
	pos[u]=++cur,id[cur]=u,tp[u]=ac;
	if(son[u])dfs2(son[u],ac);
	for(int i=fir[u];i;i=nxt[i])if(to[i]!=son[u])dfs2(to[i],to[i]);
}

inline void build(int i,int l,int r)
{
	if(l==r){sum[i]=w[id[l]];return;}
	int mid=(l+r)>>1;
	build(i<<1,l,mid),build(i<<1|1,mid+1,r);
	sum[i]=sum[i<<1]+sum[i<<1|1];
}

inline void update(int i,int l,int r,int p,int num)
{
	if(l==r){sum[i]+=num;return;}
	int mid=(l+r)>>1;
	if(p<=mid)update(i<<1,l,mid,p,num);
	else update(i<<1|1,mid+1,r,p,num);
	sum[i]=sum[i<<1]+sum[i<<1|1];
}

inline long long query(int i,int l,int r,int ql,int qr)
{
	if(qr<l||r<ql)return 0;
	if(ql<=l&&r<=qr)return sum[i];
	int mid=(l+r)>>1;
	return query(i<<1,l,mid,ql,qr)+query(i<<1|1,mid+1,r,ql,qr);
}

inline long long getans(int u,int v)
{
	long long num=0;
	while(tp[u]!=tp[v])
	{
		if(dpt[tp[u]]<dpt[tp[v]])swap(u,v);
		num+=query(1,1,n,pos[tp[u]],pos[u]);
		u=fa[tp[u]],num+=delta[u];
	}
	if(dpt[u]>dpt[v])swap(u,v);
	num+=query(1,1,n,pos[u],pos[v]);
	if(tp[u]==u)num+=delta[fa[u]];
	return num;
}

inline int LCA(int u,int v)
{
	while(tp[u]!=tp[v])
	{
		if(dpt[tp[u]]<dpt[tp[v]])swap(u,v);u=fa[tp[u]];
	}
	return dpt[u]<dpt[v]?u:v;
}

int main()
{
	n=getint(),m=getint();
	for(int i=1;i<=n;i++)A[i]=getint();
	for(int i=1;i<=n;i++)w[i]=getint();
	A[++n]=INF;
	for(int i=1;i<=n;i++)
	{
		while(top&&A[i]>A[stk[top]])newnode(i,stk[top--]);
		stk[++top]=i;
	}
	dfs1(n),dfs2(n,n),build(1,1,n);
	while(m--)
	{
		int op=getint();
		if(op&1)
		{
			int u=getint(),v=getint();
			update(1,1,n,pos[u],v),delta[u]+=v;
			if(son[u])update(1,1,n,pos[son[u]],v);
		}
		else
		{
			int u=getint(),v=getint(),lca=LCA(u,v);
			if(lca==max(u,v))
			{
				if(fa[lca]==n)printf("?
");
				else printf("%lld
",getans(u,v)+getans(fa[lca],fa[lca]));
			}
			else
			{
				if(lca==n)printf("?
");
				else printf("%lld
",getans(u,v));
			}
		}
	}
}

原文地址:https://www.cnblogs.com/Darknesses/p/12957290.html