您的位置:首页 > 其它

【BZOJ4353】Play with tree,树链剖分线段树

2016-09-13 20:52 351 查看
传送门

思路:

毒瘤数据结构

维护区间最小值及个数,区间0的个数

标记分为覆盖标记和增值标记

1操作直接覆盖

2操作取路径最小值,再判断增值

边链剖注意减去1节点的贡献

细节太多全靠自己

我反正是写了2h……

#include<cstdio>
#include<iostream>
#include<cstring>
#define M 100005
#define LL long long
using namespace std;
int n,m,tot,cnt;
int first[M],siz[M],top[M],son[M],pre[M],L[M],fa[M],sum[M<<2],dep[M],mi_sum[M<<2];
LL mi[M<<2],lazy[M<<2],cover[M<<2];
int in()
{
char ch=getchar();int t=0;bool f=0;
while (ch<'0'||ch>'9') f=(ch=='-'),ch=getchar();
while (ch>='0'&&ch<='9') t=(t<<1)+(t<<3)+ch-48,ch=getchar();
return f?-t:t;
}
struct edge{
int u,v,next,w;
}e[M<<1];
void add(int x,int y,int z)
{
e[++tot]=(edge){x,y,first[x],z};first[x]=tot;
e[++tot]=(edge){y,x,first[y],z};first[y]=tot;
}
void dfs1(int x)
{
siz[x]=1;
for (int i=first[x];i;i=e[i].next)
if (e[i].v!=fa[x])
fa[e[i].v]=x,
dep[e[i].v]=dep[x]+1,
dfs1(e[i].v),
siz[x]+=siz[e[i].v],
son[x]=(siz[son[x]]<siz[e[i].v]?e[i].v:son[x]);
}
void dfs2(int x,int tp)
{
L[x]=++cnt;
pre[cnt]=x;
top[x]=tp;
if (son[x]) dfs2(son[x],tp);
else return;
for (int i=first[x];i;i=e[i].next)
if (e[i].v!=fa[x]&&e[i].v!=son[x])
dfs2(e[i].v,e[i].v);
}
void build(int rt,int begin,int end)
{
mi_sum[rt]=sum[rt]=end-begin+1;
if (begin==end) return;
int mid=begin+end>>1;
build(rt<<1,begin,mid);
build(rt<<1|1,mid+1,end);
}
void pushdown(int rt,int begin,int end)
{
int mid=begin+end>>1;
if (cover[rt]!=-1)
{
lazy[rt]=lazy[rt<<1]=lazy[rt<<1|1]=0;
cover[rt<<1]=cover[rt<<1|1]=cover[rt];
mi[rt<<1]=mi[rt<<1|1]=cover[rt];
mi_sum[rt<<1]=mid-begin+1;
mi_sum[rt<<1|1]=end-mid;
if (!cover[rt])
sum[rt<<1]=mid-begin+1,
sum[rt<<1|1]=end-mid;
else
sum[rt<<1]=sum[rt<<1|1]=0;
cover[rt]=-1;
}
else if (lazy[rt])
{
if (cover[rt<<1]!=-1) cover[rt<<1]+=lazy[rt];
else lazy[rt<<1]+=lazy[rt];
if (cover[rt<<1|1]!=-1) cover[rt<<1|1]+=lazy[rt];
else lazy[rt<<1|1]+=lazy[rt];
mi[rt<<1]+=lazy[rt];
if (!mi[rt<<1])
sum[rt<<1]=mi_sum[rt<<1];
else
sum[rt<<1]=0;
mi[rt<<1|1]+=lazy[rt];
if (!mi[rt<<1|1])
sum[rt<<1|1]=mi_sum[rt<<1|1];
else
sum[rt<<1|1]=0;
lazy[rt]=0;
}
}
void pushup(int rt,int begin,int end)
{
sum[rt]=sum[rt<<1]+sum[rt<<1|1];
if (mi[rt<<1]==mi[rt<<1|1])
mi_sum[rt]=mi_sum[rt<<1]+mi_sum[rt<<1|1];
else
mi_sum[rt]=(mi[rt<<1]>mi[rt<<1|1]?mi_sum[rt<<1|1]:mi_sum[rt<<1]);
mi[rt]=min(mi[rt<<1],mi[rt<<1|1]);
}
void Seg_fill(int rt,int begin,int end,int l,int r,int val)
{
if (l<=begin&&end<=r)
{
sum[rt]=(val?0:end-begin+1);
mi[rt]=val;mi_sum[rt]=end-begin+1;
lazy[rt]=0;cover[rt]=val;
return;
}
pushdown(rt,begin,end);
int mid=begin+end>>1;
if (mid>=l) Seg_fill(rt<<1,begin,mid,l,r,val);
if (mid<r)  Seg_fill(rt<<1|1,mid+1,end,l,r,val);
pushup(rt,begin,end);
}
LL Seg_min(int rt,int begin,int end,int l,int r)
{
if (l<=begin&&end<=r) return mi[rt];
pushdown(rt,begin,end);
int mid=begin+end>>1;LL ans=1LL<<60;
if (mid>=l) ans=min(ans,Seg_min(rt<<1,begin,mid,l,r));
if (mid<r) ans=min(ans,Seg_min(rt<<1|1,mid+1,end,l,r));
return ans;
}
void Seg_pls(int rt,int begin,int end,int l,int r,LL val)
{
if (l<=begin&&end<=r)
{
mi[rt]+=val;
sum[rt]=(mi[rt]?0:mi_sum[rt]);
if (cover[rt]!=-1) cover[rt]+=val;
else lazy[rt]+=val;
return;
}
pushdown(rt,begin,end);
int mid=begin+end>>1;
if (mid>=l) Seg_pls(rt<<1,begin,mid,l,r,val);
if (mid<r)  Seg_pls(rt<<1|1,mid+1,end,l,r,val);
pushup(rt,begin,end);
}
void fill(int u,int v,int c)
{
for (;top[u]!=top[v];u=fa[top[u]])
{
if (dep[top[u]]<dep[top[v]]) swap(u,v);
Seg_fill(1,1,n,L[top[u]],L[u],c);
}
if (dep[u]>dep[v]) swap(u,v);
else if (dep[u]==dep[v]) return;
u=son[u];
Seg_fill(1,1,n,L[u],L[v],c);
}
LL get_min(int u,int v)
{
LL ans=1LL<<60;
for (;top[u]!=top[v];u=fa[top[u]])
{
if (dep[top[u]]<dep[top[v]]) swap(u,v);
ans=min(ans,Seg_min(1,1,n,L[top[u]],L[u]));
}
if (dep[u]>dep[v]) swap(u,v);
else if (dep[u]==dep[v]) return ans;
u=son[u];
return min(ans,Seg_min(1,1,n,L[u],L[v]));
}
void pls(int u,int v,LL c)
{
for (;top[u]!=top[v];u=fa[top[u]])
{
if (dep[top[u]]<dep[top[v]]) swap(u,v);
Seg_pls(1,1,n,L[top[u]],L[u],c);
}
if (dep[u]>dep[v]) swap(u,v);
else if (dep[u]==dep[v]) return;
u=son[u];
Seg_pls(1,1,n,L[u],L[v],c);
}
main()
{
n=in();m=in();
for (int i=1;i<n;++i) add(in(),in(),0);
dfs1(1);
dfs2(1,1);
build(1,1,n);
memset(cover,-1,sizeof(cover));
for (int p,u,v,c;m;--m)
{
p=in();u=in();v=in();c=in();
if (p==1)
fill(u,v,c);
else
p=get_min(u,v),
pls(u,v,p+c<0?-p:c);
printf("%d\n",sum[1]-(Seg_min(1,1,n,L[1],L[1])==0));
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: