3589: 动态树|树链剖分|线段树

来源:互联网 发布:演唱会软件推荐 编辑:程序博客网 时间:2024/06/13 20:05

直接树链剖分,然后查询一段路径的时候顺便在线段树中打上标记,如果再查到这个地方的时候就直接忽略掉这部分对答案的贡献

#include<algorithm>#include<iostream>#include<cstdlib>#include<cstring>#include<cstdio>#include<vector>#include<cmath>#include<queue>#include<ctime>#include<set>#include<map>#define N 800020#define inf 1e9#define pa pair<int,int>using namespace std;int sc(){    int i=0; char c=getchar();    while(c>'9'||c<'0')c=getchar();    while(c>='0'&&c<='9')i=i*10+c-'0',c=getchar();    return i;}const long long mod=2147483648LL;long long sum[N],tag[N];int tim[N],mn[N];int deep[N],fa[N],top[N],size[N];int S[N],T[N];int head[N],nxt[N],lst[N];int n,tot,cnt,Q;void insert(int x,int y){    lst[++tot]=y; nxt[tot]=head[x]; head[x]=tot;    lst[++tot]=x; nxt[tot]=head[y]; head[y]=tot;}void dfs1(int x,int f){    size[x]=1;    for(int i=head[x];i;i=nxt[i])        if(lst[i]!=f)        {            fa[lst[i]]=x;            deep[lst[i]]=deep[x]+1;            dfs1(lst[i],x);            size[x]+=size[lst[i]];        }}void dfs2(int x,int htp){    int k=0; top[x]=htp; S[x]=T[x]=++cnt;     for(int i=head[x];i;i=nxt[i])        if(lst[i]!=fa[x]&&size[lst[i]]>size[k])k=lst[i];    if(!k)return; dfs2(k,htp);    for(int i=head[x];i;i=nxt[i])        if(lst[i]!=fa[x]&&lst[i]!=k)            dfs2(lst[i],lst[i]);    T[x]=cnt;}void push_down(int x,int l,int mid,int r){    int L=x<<1,R=x<<1|1;    if(tag[x])    {        tag[L]=(tag[L]+tag[x])%mod;        tag[R]=(tag[R]+tag[x])%mod;        sum[L]=(sum[L]+tag[x]*(mid-l+1))%mod;        sum[R]=(sum[R]+tag[x]*(r-mid))%mod;        tag[x]=0;    }    tim[L]=max(tim[L],mn[x]);    tim[R]=max(tim[R],mn[x]);    mn[L]=max(mn[L],mn[x]);    mn[R]=max(mn[R],mn[x]);}void change(int x,int L,int R,int l,int r,long long delta){    if(L==l&&R==r)    {        tag[x]=(tag[x]+delta)%mod;        sum[x]=(sum[x]+delta*(r-l+1))%mod;        return ;    }    int mid=L+R>>1;    push_down(x,L,mid,R);    if(r<=mid) change(x<<1,L,mid,l,r,delta);    else if(l>mid) change(x<<1|1,mid+1,R,l,r,delta);    else change(x<<1,L,mid,l,mid,delta),change(x<<1|1,mid+1,R,mid+1,r,delta);    sum[x]=sum[x<<1]+sum[x<<1|1];    //tim[x]=max(tim[x<<1],tim[x<<1|1]);}long long ask(int x,int L,int R,int l,int r,int TI){    int mid=L+R>>1;    if(L==l&&R==r)    {        if(mn[x]==TI)return 0;        else if(tim[x]<TI)        {            mn[x]=tim[x]=TI;            return sum[x];        }        else        {            long long ans=ask(x<<1,L,mid,l,mid,TI)+ask(x<<1|1,mid+1,R,mid+1,r,TI);            mn[x]=tim[x]=TI;            return ans;        }    }    long long ans=0; push_down(x,L,mid,R);    if(r<=mid) ans=ask(x<<1,L,mid,l,r,TI);    else if(l>mid) ans=ask(x<<1|1,mid+1,R,l,r,TI);    else ans=ask(x<<1,L,mid,l,mid,TI)+ask(x<<1|1,mid+1,R,mid+1,r,TI);    tim[x]=max(tim[x<<1],tim[x<<1|1]);    mn[x]=min(mn[x<<1],mn[x<<1|1]);    return ans;}long long query(int x,int y,int TI){    long long ans=0;    while(top[x]!=top[y])    {        if(deep[top[x]]<deep[top[y]])swap(x,y);        ans+=ask(1,1,n,S[top[x]],S[x],TI);        x=fa[top[x]];    }    if(deep[x]>deep[y])swap(x,y);    ans+=ask(1,1,n,S[x],S[y],TI);    return ans%mod;}int main(){    n=sc();    for(int i=1;i<n;i++)    {        int x=sc(),y=sc();        insert(x,y);    }    dfs1(1,0);dfs2(1,1);    Q=sc();    for(int i=1;i<=Q;i++)    {        int opt=sc(),s;        if(opt==0)        {            int x=sc(),y=sc();            change(1,1,n,S[x],T[x],y);        }        else        {            long long ans=0;            for(int j=1,s=sc();j<=s;j++)            {                int x=sc(),y=sc();                ans+=query(x,y,i);            }            printf("%lld\n",ans%mod);        }    }           return 0;}
0 0
原创粉丝点击