bzoj 1036 洛谷P2590 code[vs] 2460 树的统计
code[vs] 2460
洛谷P2590
bzoj 1036好像bzoj上的数据比较多
<mark>这道题注意可能是负数,因此求最大值的时候要初始化为-inf</mark>
//#include"bits/stdc++.h"
#include"iostream"
#include"cstring"
#include"cstdio"
using namespace std;
typedef long long LL;
const int maxn=5e5+5;
const LL linf=1e15;
int N,M,Q,R,Time,tot;
LL a[maxn];
LL dep[maxn],sz[maxn],fa[maxn];
LL top[maxn];//用来跳转到这条重链的起始节点
LL sa[maxn];//排第i个的原来是第sa[i]个节点
LL rnk[maxn];//第i个节点排rnk[i]
LL son[maxn];//保存当前节点的重节点
struct Edge
{
int t,v,nxt;
};
Edge E[maxn<<1];
int head[maxn];
void AddEdge(int aa,int bb,int val)
{
E[++tot].t=bb;
E[tot].v=val;
E[tot].nxt=head[aa];
head[aa]=tot;
}
void dfs1(int u,int pre,int deep)
{
dep[u]=deep;
fa[u]=pre;
sz[u]=1;
for(int i=head[u]; i!=-1; i=E[i].nxt)
{
int t=E[i].t;
if(t==pre)continue;
dfs1(t,u,deep+1);
sz[u]+=sz[t];
if(son[u]==-1)son[u]=t;//没有重节点
else if(sz[t]>sz[son[u]])son[u]=t;//比原来的大
}
}
void dfs2(int u,int uu)//uu为起始重节点
{
top[u]=uu;
rnk[u]=++Time;//Time为时间顺序
sa[Time]=u;
if(son[u]==-1)return ;//如果u不在重链上就不继续往下
dfs2(son[u],uu);
for(int i=head[u]; i!=-1; i=E[i].nxt)
{
int t=E[i].t;
if(t==fa[u])continue;
if(t!=son[u])dfs2(t,t);//如果不是重节点,就那么top就会变
}
}
LL lazy[maxn<<2],sum[maxn<<2],Max[maxn<<2];//线段树的
void pushup(int id)
{
sum[id]=sum[id<<1]+sum[id<<1|1];
Max[id]=max(Max[id<<1],Max[id<<1|1]);
}
void Build(int id,int L,int R)
{
lazy[id]=0;
if(L==R)
{
sum[id]=a[sa[L]];
Max[id]=sum[id];
return ;
}
int mid=(L+R)>>1;
Build(id<<1,L,mid);
Build(id<<1|1,mid+1,R);
pushup(id);
}
void pushdown(int id,int L,int R)
{
if(lazy[id]==0)return ;
int mid=(L+R)>>1;
lazy[id<<1]+=lazy[id];
lazy[id<<1|1]+=lazy[id];
sum[id<<1]+=lazy[id]*(mid-L+1);
sum[id<<1|1]+=lazy[id]*(R-mid);
lazy[id]=0;
}
void Add(int id,int L,int R,int qL,int qR,int val)//在线段树[qL,qR]上加权值val
{
if(qL<=L&&qR>=R)
{
lazy[id]+=val;
sum[id]+=(LL)val*(R-L+1);
Max[id]+=val;
return ;
}
pushdown(id,L,R);
int mid=(L+R)>>1;
if(qL<=mid)Add(id<<1,L,mid,qL,qR,val);
if(qR>mid)Add(id<<1|1,mid+1,R,qL,qR,val);
pushup(id);
}
void AddTree(int u,int v,int val)//在树上加
{
while(top[u]!=top[v])
{
if(dep[top[u]]<dep[top[v]])swap(u,v);//重节点深度大的放前面
int qL=rnk[top[u]],qR=rnk[u];
Add(1,1,N,qL,qR,val);//先把重链加上
u=fa[top[u]];
}
if(dep[u]>dep[v])swap(u,v);//深度浅的rnk排在前面些
Add(1,1,N,rnk[u],rnk[v],val);
}
LL query(int id,int L,int R,int qL,int qR)//线段树上询问[qL,qR]的和
{
if(qL<=L&&qR>=R)return sum[id];
pushdown(id,L,R);
int mid=(L+R)>>1;
LL res=0;
if(qL<=mid)res+=query(id<<1,L,mid,qL,qR);
if(qR>mid)res+=query(id<<1|1,mid+1,R,qL,qR);
return res;
}
LL queryMax(int id,int L,int R,int qL,int qR)//线段树上询问[qL,qR]的最大值
{
if(qL<=L&&qR>=R)return Max[id];
pushdown(id,L,R);
int mid=(L+R)>>1;
LL mx=-linf;
if(qL<=mid)mx=max(mx,queryMax(id<<1,L,mid,qL,qR));
if(qR>mid)mx=max(mx,queryMax(id<<1|1,mid+1,R,qL,qR));
return mx;
}
LL queryTree(int u,int v)//树链上询问u节点到v节点的权值和
{
LL res=0;
while(top[u]!=top[v])
{
if(dep[top[u]]<dep[top[v]])swap(u,v);//重节点深度大的放前面
int qL=rnk[top[u]],qR=rnk[u];
res+=query(1,1,N,qL,qR);//先把重链加上
u=fa[top[u]];
}
if(dep[u]>dep[v])swap(u,v);//深度浅的rnk排在前面些
int qL=rnk[u],qR=rnk[v];
res+=query(1,1,N,qL,qR);
return res;
}
void Addson(int u,int val)//在u节点以及他的子节点上加权值val
{
int qL=rnk[u];
int qR=rnk[u]+sz[u]-1;
Add(1,1,N,qL,qR,val);
}
LL queryson(int u)//询问u节点以及子节点的权值和
{
int qL=rnk[u];
int qR=rnk[u]+sz[u]-1;
return query(1,1,N,qL,qR);
}
LL queryMaxTree(int u,int v)//询问树链上u节点到v节点的最大值
{
LL mx=-linf;
while(top[u]!=top[v])
{
if(dep[top[u]]<dep[top[v]])swap(u,v);//重节点深度大的放前面
int qL=rnk[top[u]],qR=rnk[u];
mx=max(mx,queryMax(1,1,N,qL,qR));//先把重链加上
u=fa[top[u]];
}
if(dep[u]>dep[v])swap(u,v);//深度浅的rnk排在前面些
int qL=rnk[u],qR=rnk[v];
mx=max(mx,queryMax(1,1,N,qL,qR));
return mx;
}
int main()
{
cin>>N;
{
memset(head,-1,sizeof head);
memset(son,-1,sizeof son);
tot=Time=0;
for(int i=1; i<N; i++)
{
int u,v;
scanf("%d%d",&u,&v);
AddEdge(u,v,1);
AddEdge(v,u,1);
}
for(int i=1; i<=N; i++)scanf("%lld",a+i);
dfs1(1,-1,0);
dfs2(1,1);
Build(1,1,N);
int t1,t2,v=0;
char cmd[10];
cin>>M;
while(M--)
{
scanf("%s",cmd);
if(cmd[1]=='M')//t1到t2最大值
{
scanf("%d%d",&t1,&t2);
printf("%lld\n",queryMaxTree(t1,t2));
}
else if(cmd[1]=='S')//t1到t2的和
{
scanf("%d%d",&t1,&t2);
printf("%lld\n",queryTree(t1,t2));
}
else if(cmd[1]=='H')//修改点t1
{
scanf("%d%d",&t1,&v);
LL val=queryTree(t1,t1);
AddTree(t1,t1,v-val);
}
}
}
}
/* 3 1 2 2 3 -804042 -486095 -54882 10 QMAX 3 2 CHANGE 1 3 QMAX 1 2 CHANGE 3 3 QSUM 1 3 QMAX 1 1 QSUM 3 3 QMAX 2 2 QMAX 1 2 QMAX 3 1 */
洛谷 P3178 树上操作
P3178 树上操作
WA的话把权值开成long long 试一试
//#include"bits/stdc++.h"
#include"iostream"
#include"cstring"
#include"cstdio"
using namespace std;
typedef long long LL;
const int maxn=1e6+5;
int N,M,Q,R,Time,tot;
LL a[maxn];
LL dep[maxn],sz[maxn],fa[maxn];
LL top[maxn];//用来跳转到这条重链的起始节点
LL sa[maxn];//排第i个的原来是第sa[i]个节点
LL rnk[maxn];//第i个节点排rnk[i]
LL son[maxn];//保存当前节点的重节点
struct Edge
{
int t,v,nxt;
};
Edge E[maxn<<1];
int head[maxn];
void AddEdge(int aa,int bb,int val)
{
E[++tot].t=bb;
E[tot].v=val;
E[tot].nxt=head[aa];
head[aa]=tot;
}
void dfs1(int u,int pre,int deep)
{
dep[u]=deep;
fa[u]=pre;
sz[u]=1;
for(int i=head[u]; i!=-1; i=E[i].nxt)
{
int t=E[i].t;
if(t==pre)continue;
dfs1(t,u,deep+1);
sz[u]+=sz[t];
if(son[u]==-1)son[u]=t;//没有重节点
else if(sz[t]>sz[son[u]])son[u]=t;//比原来的大
}
}
void dfs2(int u,int uu)//uu为起始重节点
{
top[u]=uu;
rnk[u]=++Time;//Time为时间顺序
sa[Time]=u;
if(son[u]==-1)return ;//如果u不在重链上就不继续往下
dfs2(son[u],uu);
for(int i=head[u]; i!=-1; i=E[i].nxt)
{
int t=E[i].t;
if(t==fa[u])continue;
if(t!=son[u])dfs2(t,t);//如果不是重节点,就那么top就会变
}
}
LL lazy[maxn<<2],sum[maxn<<2];//线段树的
void pushup(int id)
{
sum[id]=sum[id<<1]+sum[id<<1|1];
}
void Build(int id,int L,int R)
{
lazy[id]=0;
if(L==R)
{
sum[id]=a[sa[L]];
return ;
}
int mid=(L+R)>>1;
Build(id<<1,L,mid);
Build(id<<1|1,mid+1,R);
pushup(id);
}
void pushdown(int id,int L,int R)
{
if(lazy[id]==0)return ;
int mid=(L+R)>>1;
lazy[id<<1]+=lazy[id];
lazy[id<<1|1]+=lazy[id];
sum[id<<1]+=lazy[id]*(mid-L+1);
sum[id<<1|1]+=lazy[id]*(R-mid);
lazy[id]=0;
}
void Add(int id,int L,int R,int qL,int qR,LL val)
{
if(qL<=L&&qR>=R)
{
lazy[id]+=val;
sum[id]+=(LL)val*(R-L+1);
return ;
}
pushdown(id,L,R);
int mid=(L+R)>>1;
if(qL<=mid)Add(id<<1,L,mid,qL,qR,val);
if(qR>mid)Add(id<<1|1,mid+1,R,qL,qR,val);
pushup(id);
}
void AddTree(int u,int v,LL val)
{
while(top[u]!=top[v])
{
if(dep[top[u]]<dep[top[v]])swap(u,v);//重节点深度大的放前面
int qL=rnk[top[u]],qR=rnk[u];
Add(1,1,N,qL,qR,val);//先把重链加上
u=fa[top[u]];
}
if(dep[u]>dep[v])swap(u,v);//深度浅的rnk排在前面些
Add(1,1,N,rnk[u],rnk[v],val);
}
LL query(int id,int L,int R,int qL,int qR)
{
if(qL<=L&&qR>=R)return sum[id];
pushdown(id,L,R);
int mid=(L+R)>>1;
LL res=0;
if(qL<=mid)res+=query(id<<1,L,mid,qL,qR);
if(qR>mid)res+=query(id<<1|1,mid+1,R,qL,qR);
return res;
}
LL queryTree(int u,int v)
{
LL res=0;
while(top[u]!=top[v])
{
if(dep[top[u]]<dep[top[v]])swap(u,v);//重节点深度大的放前面
int qL=rnk[top[u]],qR=rnk[u];
res+=query(1,1,N,qL,qR);//先把重链加上
u=fa[top[u]];
}
if(dep[u]>dep[v])swap(u,v);//深度浅的rnk排在前面些
int qL=rnk[u],qR=rnk[v];
res+=query(1,1,N,qL,qR);
return res;
}
void Addson(int u,LL val)
{
int qL=rnk[u];
int qR=rnk[u]+sz[u]-1;
Add(1,1,N,qL,qR,val);
}
LL queryson(int u)
{
int qL=rnk[u];
int qR=rnk[u]+sz[u]-1;
return query(1,1,N,qL,qR);
}
int main()
{
cin>>N>>M;
{
memset(head,-1,sizeof head);
memset(son,-1,sizeof son);
tot=Time=0;
for(int i=1; i<=N; i++)scanf("%lld",a+i);
for(int i=1; i<N; i++)
{
int u,v;
scanf("%d%d",&u,&v);
AddEdge(u,v,1);
AddEdge(v,u,1);
}
dfs1(1,-1,0);
dfs2(1,1);
Build(1,1,N);
int cmd,t1,t2;
LL v=0;
while(M--)
{
cin>>cmd;
if(cmd==1)
{
scanf("%d%lld",&t1,&v);
AddTree(t1,t1,v);
}
else if(cmd==2)
{
scanf("%d%lld",&t1,&v);
Addson(t1,v);
}
else if(cmd==3)
{
scanf("%d",&t1);
printf("%lld\n",queryTree(1,t1));
}
}
}
}