您的位置:首页 > 其它

2017.6.27 树上操作 思考记录

2017-06-27 17:40 232 查看
        这个题是以前应该做过、、

        子树的话注意size就可以了,另外还要开longlong

       另外标记是+-的,不是覆盖的、、

       下传时要注意r-mid   (开括号开错调了半天,数学太好了)

      下传时应使用纯树上信息

码:

#include<iostream>
#include<cstdio>
#include<vector>
#include<algorithm>
using namespace std;
#define zuo o<<1,l,mid
#define you o<<1|1,mid+1,r
#define N 100005
vector<int>v
;
long long ans,he[N<<2],i,sz
,d
,op,n,m,bj[N<<2],dui
,fu
,lzhi
,zhi
,top
,a,b,c,tot,hson
;
int x,y;
void dfs1(int now,int fa,int shen)
{
fu[now]=fa;
d[now]=shen;
sz[now]=1;
for(int i=0;i<v[now].size();i++)
{
int nd=v[now][i];
if(nd==fa)continue;
dfs1(nd,now,shen+1);
if(sz[nd]>sz[hson[now]])hson[now]=nd;
sz[now]+=sz[nd];
}
}
void dfs2(int now,int tap)
{
top[now]=tap;
dui[now]=++tot;
zhi[tot]=lzhi[now];
if(hson[now]!=0)dfs2(hson[now],tap);
for(int i=0;i<v[now].size();i++)
{
int nd=v[now][i];
if(nd==fu[now]||nd==hson[now])continue;
dfs2(nd,nd);
}
}
void up(int o)
{
he[o]=he[o<<1]+he[o<<1|1];
}

void jian(int o,int l,int r)
{
if(l==r)
{
he[o]=zhi[l];
return;
}
int mid=(l+r)>>1;
jian(zuo);
jian(you);
up(o);
}

void down(int o,int l,int r)
{
if(bj[o]!=0)
{
int mid=(l+r)>>1;
he[o<<1]+=bj[o]*(mid-l+1);
he[o<<1|1]+=bj[o]*(r-(mid+1)+1);
bj[o<<1]+=bj[o];
bj[o<<1|1]+=bj[o];
bj[o]=0;
}
}

void zhao(int o,int l,int r)
{
if(a<=l&&b>=r)
{
if(op==3)
ans+=he[o];
else {he[o]+=c*(r-l+1);bj[o]+=c;}
return;
}
down(o,l,r);
int mid=(l+r)>>1;
if(a<=mid)zhao(zuo);
if(b>mid)zhao(you);
up(o);
}
void workgai1(int x,int y)
{
a=dui[x];
b=dui[x];
c=y;
zhao(1,1,tot);
}
void workgai2(int x,int y)
{
a=dui[x];
b=dui[x]+sz[x]-1;
c=y;
zhao(1,1,tot);
}

void workzhao(int y)
{
ans=0;
x=1;
while(top[x]!=top[y])
{
if(d[top[x]]>d[top[y]])swap(x,y);
a=dui[top[y]];
b=dui[y];
zhao(1,1,tot);
y=fu[top[y]];
}
if(d[x]>d[y])swap(x,y);
a=dui[x];
b=dui[y];
zhao(1,1,tot);
}
int main()
{
scanf("%lld%lld",&n,&m);
for(i=1;i<=n;i++)scanf("%lld",&lzhi[i]);
for(i=1;i<n;i++)
{
scanf("%d%d",&x,&y);
v[x].push_back(y);
v[y].push_back(x);
}

dfs1(1,1,1);
dfs2(1,1);
jian(1,1,n);

for(i=1;i<=m;i++)
{
scanf("%lld",&op);
if(op==1)
{
scanf("%d%d",&x,&y);
workgai1(x,y);
}
if(op==2)
{
scanf("%d%d",&x,&y);
workgai2(x,y);
}
if(op==3)
{
scanf("%d",&x);
workzhao(x);
printf("%lld\n",ans);
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: