zoukankan      html  css  js  c++  java
  • 联考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));
    			}
    		}
    	}
    }
    

  • 相关阅读:
    loadrunne-- Analysis 分析器
    Fiddler抓包工具详细介绍
    在 Windows 10 x64 上安装及使用 ab 工具的流程
    Ab工具基本使用
    ab压测返回结果解析
    VMware Workstation 14 Pro永久激活密钥
    通用接口测试用例设计
    线段树の二 区间乘+区间加
    线段树の一 区间和
    C++位运算
  • 原文地址:https://www.cnblogs.com/Darknesses/p/12957290.html
Copyright © 2011-2022 走看看