联考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("?\n");
else printf("%lld\n",getans(u,v)+getans(fa[lca],fa[lca]));
}
else
{
if(lca==n)printf("?\n");
else printf("%lld\n",getans(u,v));
}
}
}
}