树链剖分练习总结

 

T1 洛谷p3384树链剖分模板

传送门

题目大意:1 区间加 2 区间和 3子树加 4子树和

代码:

#include<cstdio>
#include<iostream>
using namespace std;
const int maxn=500005;
typedef long long LL;
int n,m,u,v,t,r,sumedge,temp;
LL mod;
int head[maxn],son[maxn],dad[maxn],top[maxn],heavy_son[maxn];
int id[maxn],real[maxn],depth[maxn],a[maxn];
struct Edge{
    int x,y,nxt;
    Edge(int x=0,int y=0,int nxt=0):
        x(x),y(y),nxt(nxt){}
}edge[maxn];
struct segment_tree{
    LL l,r,sum,tag;
}tr[maxn];
void add(int x,int y){
    edge[++sumedge]=Edge(x,y,head[x]);
    head[x]=sumedge;
}
void dfs1(int k,int fa){
    dad[k]=fa;depth[k]=depth[fa]+1;
    son[k]=1;
    for(int i=head[k];i;i=edge[i].nxt){
        int v=edge[i].y;
        if(v!=fa){
            dfs1(v,k);
            son[k]+=son[v];
            if(!heavy_son[k]||son[heavy_son[k]]<son[v])
            heavy_son[k]=v;
        }
    }
}
void dfs2(int k,int fir){
    top[k]=fir;id[k]=++temp;
    real[temp]=k;
    if(!heavy_son[k])return;
    dfs2(heavy_son[k],fir);
    for(int i=head[k];i;i=edge[i].nxt){
        int v=edge[i].y;
        if(v!=dad[k]&&v!=heavy_son[k])
        dfs2(v,v);
    }
}
void pushup(int rt){
    tr[rt].sum=tr[rt<<1].sum+tr[rt<<1|1].sum;
}
void pushdown(int rt){
    tr[rt<<1].tag+=tr[rt].tag;
    tr[rt<<1].sum+=tr[rt].tag*(tr[rt<<1].r-tr[rt<<1].l+1);
    tr[rt<<1|1].tag+=tr[rt].tag;
    tr[rt<<1|1].sum+=tr[rt].tag*(tr[rt<<1|1].r-tr[rt<<1|1].l+1);
    tr[rt].tag=0;
    return;
}

void build(int rt,int l,int r){
    tr[rt].l=l;tr[rt].r=r;
    if(l==r){
        tr[rt].sum=a[real[l]];
        return;
    }
    int mid=(l+r)>>1;
    build(rt<<1,l,mid);build(rt<<1|1,mid+1,r);
    pushup(rt);
}

void update(int now,int ll,int rr,int x){
    if(ll<=tr[now].l&&tr[now].r<=rr){
        tr[now].sum+=(tr[now].r-tr[now].l+1)*x;
        tr[now].tag+=x;
        return;
    }
    pushdown(now);
    int mid=(tr[now].l+tr[now].r)>>1;
    if(rr<=mid)update(now<<1,ll,rr,x);
    else if(ll>mid)update(now<<1|1,ll,rr,x);
    else {
        update(now<<1,ll,mid,x);
        update(now<<1|1,mid+1,rr,x);
    }
    pushup(now);//***
}
LL query_sum(int now,int ll,int rr){
    if(ll<=tr[now].l&&tr[now].r<=rr){
        return tr[now].sum;
    }
    pushdown(now);
    int mid=(tr[now].l+tr[now].r)>>1;
    if(rr<=mid)return query_sum(now<<1,ll,rr);
    else if(ll>mid)return query_sum(now<<1|1,ll,rr);
    else{
        return query_sum(now<<1,ll,mid)+query_sum(now<<1|1,mid+1,rr);
    }
}
void change(int u,int v,LL x){
    int tu=top[u],tv=top[v];
    while(tu!=tv){
        if(depth[tu]<depth[tv]){
            swap(tu,tv);swap(u,v);
        }
        update(1,id[tu],id[u],x);
        u=dad[tu];
        tu=top[u];
    }
    if(depth[u]>depth[v])swap(u,v);
    update(1,id[u],id[v],x);
}
int find_sum(int u,int v){
    LL sum=0;
    int tu=top[u],tv=top[v];
    while(tu!=tv){
        if(depth[tu]<depth[tv]){
            swap(tu,tv);
            swap(u,v);
        }
        sum+=query_sum(1,id[tu],id[u]);
        sum%=mod;
        u=dad[tu];
        tu=top[u];
    }
    if(depth[u]>depth[v])swap(u,v);
    sum+=query_sum(1,id[u],id[v]);
    return sum%mod;
}

void root_add(int now,LL x){
    int begin=id[now];
    int ed=id[now]+son[now]-1;
    update(1,begin,ed,x);
}
LL root_sum(int now){
    int begin=id[now];
    int ed=id[now]+son[now]-1;
    return query_sum(1,begin,ed)%mod;
}

int main(){
    scanf("%d%d%d%lld",&n,&m,&r,&mod);
    for(int i=1;i<=n;i++)scanf("%d",&a[i]);
    for(int i=1;i<n;i++){
        scanf("%d%d",&u,&v);
        add(u,v);add(v,u);
    }
    dfs1(r,0);dfs2(r,r);
    build(1,1,temp);
    for(int i=0;i<m;i++){
        int t,x,y,z;
        scanf("%d",&t);
        if(t==1){
            scanf("%d%d%d",&x,&y,&z);
            change(x,y,z);
        }else if(t==2){
            scanf("%d%d",&x,&y);
            printf("%lld\n",find_sum(x,y));
        }else if(t==3){
            scanf("%d%d",&x,&y);
            root_add(x,y);
        }else if(t==4){
            scanf("%d",&x);
            printf("%lld\n",root_sum(x));
        }
    }
    return 0;
} 
AC
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define N 100009
using namespace std;

int n,m,r,p,cnt,sumedge;

int head[N],size[N],deep[N],dad[N],top[N],tpos[N],a[N],b[N];

struct Edge{
    int x,y,nxt;
    Edge(int x=0,int y=0,int nxt=0):
        x(x),y(y),nxt(nxt){}
}edge[N<<2];

void add(int x,int y){
    edge[++sumedge]=Edge(x,y,head[x]);
    head[x]=sumedge;
}

struct Tree{
    int l,r,sum,s;
}tr[N<<2];

void dfs(int x){
    size[x]=1;deep[x]=deep[dad[x]]+1;
    for(int i=head[x];i;i=edge[i].nxt){
        int v=edge[i].y;
        if(v==dad[x])continue;
        dad[v]=x;dfs(v);
        size[x]+=size[v];        
    }
}

void dfs_(int x){
    int s=0;tpos[x]=++cnt;b[cnt]=a[x];
    if(!top[x])top[x]=x;
    for(int i=head[x];i;i=edge[i].nxt){
        int v=edge[i].y;
        if(v!=dad[x]&&size[v]>size[s])s=v;
    }
    if(s){
        top[s]=top[x];
        dfs_(s);
    }
    for(int i=head[x];i;i=edge[i].nxt){
        int v=edge[i].y;
        if(v!=s&&v!=dad[x])dfs_(v);
    }
}

void pushup(int rt){
    tr[rt].sum=tr[rt<<1].sum+tr[rt<<1|1].sum;
    return ;
}

void pushdown(int rt){
    tr[rt<<1].sum=(tr[rt<<1].sum%p+(tr[rt<<1].r-tr[rt<<1].l+1)*tr[rt].s%p)%p;
    tr[rt<<1].s+=tr[rt].s;
    tr[rt<<1|1].sum=(tr[rt<<1|1].sum%p+(tr[rt<<1|1].r-tr[rt<<1|1].l+1)*tr[rt].s%p)%p;
    tr[rt<<1|1].s+=tr[rt].s;
    tr[rt].s=0;
}

void build(int rt,int l,int r){
    tr[rt].l=l;tr[rt].r=r;
    if(l==r){
        tr[rt].sum=b[l];
        return ;
    }
    int mid=(l+r)>>1;
    build(rt<<1,l,mid);
    build(rt<<1|1,mid+1,r);
    pushup(rt);
}

void change(int rt,int l,int r,int ql,int qr,int z){
    if(l>=ql&&r<=qr){
        tr[rt].sum+=(r-l+1)*z;
        tr[rt].s+=z;
        return;
    }
    pushdown(rt);
    int mid=(l+r)>>1;
    if(ql<=mid)change(rt<<1,l,mid,ql,qr,z);
    if(qr>mid)change(rt<<1|1,mid+1,r,ql,qr,z);
    pushup(rt);
}

int query_sum(int rt,int l,int r,int ql,int qr){
    if(l>=ql&&r<=qr){
        return tr[rt].sum%p;
    }
    pushdown(rt);
    int ans=0,mid=(l+r)>>1;
    if(ql<=mid)ans=(ans%p+query_sum(rt<<1,l,mid,ql,qr)%p)%p;
    if(qr>mid)ans=(ans%p+query_sum(rt<<1|1,mid+1,r,ql,qr)%p)%p;
    return ans;
}

void add_(int x,int y,int z){
    for(;top[x]!=top[y];){
        if(deep[top[x]]>deep[top[y]])swap(x,y);
        change(1,1,n,tpos[top[y]],tpos[y],z);
        y=dad[top[y]];
    }
    if(deep[x]>deep[y])swap(x,y);
    change(1,1,n,tpos[x],tpos[y],z);
}

int query(int x,int y){
    int ret=0;
    for(;top[x]!=top[y];){
        if(deep[top[y]]<deep[top[x]])swap(x,y);
        ret=(ret%p+query_sum(1,1,n,tpos[top[y]],tpos[y])%p)%p;
        y=dad[top[y]];
    }
    if(deep[x]>deep[y])swap(x,y);
    ret=(ret%p+query_sum(1,1,n,tpos[x],tpos[y])%p)%p;
    return ret;
}

int main(){
    scanf("%d%d%d%d",&n,&m,&r,&p);
    for(int i=1;i<=n;i++)scanf("%d",&a[i]);
    for(int i=1;i<n;i++){
        int x,y;
        scanf("%d%d",&x,&y);
        add(x,y);add(y,x);
    }
    dfs(r);dfs_(r);build(1,1,n);
    for(int i=1;i<=m;i++){
        int od,x,y,z;
        scanf("%d",&od);
        if(od==1){
            scanf("%d%d%d",&x,&y,&z);
            add_(x,y,z);
        }
        if(od==2){
            scanf("%d%d",&x,&y);
            printf("%d\n",query(x,y));
        }
        if(od==3){
            scanf("%d%d",&x,&z);
            change(1,1,n,tpos[x],tpos[x]+size[x]-1,z);
        }
        if(od==4){
            scanf("%d",&x);
            printf("%d\n",query_sum(1,1,n,tpos[x],tpos[x]+size[x]-1));
        }
    }
    return 0;
}
后来敲的风格换了

 

T2codevs4633[Mz]树链剖分练习

传送门

题目大意:区间加 区间和

代码:

#include<iostream>
#include<cstring>
#include<cstdio>
#define maxn 500008
using namespace std;

int n,q,sumedge,cnt;
int head[maxn],dad[maxn],top[maxn],deep[maxn],size[maxn],tpos[maxn];
struct Tree{
    int l,r,sum,s;
}tr[maxn<<2];

struct Edge{
    int x,y,nxt;
    Edge(int x=0,int y=0,int nxt=0):
        x(x),y(y),nxt(nxt){}
}edge[maxn<<1];

void add(int x,int y){
    edge[++sumedge]=Edge(x,y,head[x]);
    head[x]=sumedge;
}

void pushup(int rt){
    tr[rt].sum=tr[rt<<1].sum+tr[rt<<1|1].sum;
    return;
}

void pushdown(int rt){
    if(!tr[rt].s)return;
    tr[rt<<1].s+=tr[rt].s;tr[rt<<1].sum+=(tr[rt<<1].r-tr[rt<<1].l+1)*tr[rt].s;
    tr[rt<<1|1].s+=tr[rt].s;tr[rt<<1|1].sum+=(tr[rt<<1|1].r-tr[rt<<1|1].l+1)*tr[rt].s;
    tr[rt].s=0;return;
}

void build(int rt,int l,int r){
    tr[rt].l=l;tr[rt].r=r;
    if(l==r)return;
    int mid=(l+r)>>1;
    build(rt<<1,l,mid);build(rt<<1|1,mid+1,r);
    return;
}

int query_sum(int rt,int l,int r,int ql,int qr){
    pushdown(rt);
    if(l>=ql&&r<=qr){
        return tr[rt].sum;
    }
    int ans=0,mid=(l+r)>>1;
    if(ql<=mid)ans+=query_sum(rt<<1,l,mid,ql,qr);
    if(qr>mid)ans+=query_sum(rt<<1|1,mid+1,r,ql,qr);
    return ans;
}

void change(int rt,int l,int r,int ql,int qr){
    pushdown(rt);
    if(l>=ql&&r<=qr){
        tr[rt].sum+=(tr[rt].r-tr[rt].l+1);
        tr[rt].s++;
        return;
    }
    int mid=(l+r)>>1;
    if(ql<=mid)change(rt<<1,l,mid,ql,qr);
    if(qr>mid)change(rt<<1|1,mid+1,r,ql,qr);
    pushup(rt);
}

void dfs(int x){
    size[x]=1;deep[x]=deep[dad[x]]+1;
    for(int i=head[x];i;i=edge[i].nxt){
        int v=edge[i].y;
        if(v==dad[x])continue;
        dad[v]=x;dfs(v);
        size[x]+=size[v];
    }
}

void dfs_(int x){
    int s=0;tpos[x]=++cnt;
    if(!top[x])top[x]=x;
    for(int i=head[x];i;i=edge[i].nxt){
        int v=edge[i].y;
        if(v!=dad[x]&&size[v]>size[s])s=v;
    }
    if(s){
        top[s]=top[x];
        dfs_(s);
    }
    for(int i=head[x];i;i=edge[i].nxt){
        int v=edge[i].y;
        if(v!=dad[x]&&v!=s)dfs_(v);
    }
}

int lca(int x,int y){
    for(;top[x]!=top[y];){
        if(deep[top[x]]>deep[top[y]])swap(x,y);
        y=dad[top[y]];
    }
    if(deep[x]>deep[y])return y;
    return x;
}

void query(int x,int y){
    int ret=0;
    for(;top[x]!=top[y];){
        if(deep[top[x]]>deep[top[y]])swap(x,y);
        ret+=query_sum(1,1,n,tpos[top[y]],tpos[y]);
        y=dad[top[y]];
    }
    if(deep[x]>deep[y])swap(x,y);
    ret+=query_sum(1,1,n,tpos[x],tpos[y]);
    printf("%d\n",ret);
}

void change_(int x,int y){
    for(;top[x]!=top[y];){
        if(deep[top[x]]>deep[top[y]])swap(x,y);
        change(1,1,n,tpos[top[y]],tpos[y]);
        y=dad[top[y]];
    }
    if(deep[x]>deep[y])swap(x,y);
    change(1,1,n,tpos[x],tpos[y]);
}

int main(){
    scanf("%d",&n);
    for(int i=1;i<n;i++){
        int x,y;
        scanf("%d%d",&x,&y);
        add(x,y);add(y,x);
    }
    dfs(1);dfs_(1);build(1,1,n);
    scanf("%d",&q);
    for(int i=1;i<=q;i++){
        int a,b,c;
        scanf("%d%d%d",&a,&b,&c);
        if(a==1)change_(b,c);
        else query(b,c);
    }
    return 0;
}

AC
AC

 

 

T3洛谷P2590树的统计

传送门

题目大意:单点修改 区间和 区间最大值

代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#define maxn 100005
#define inf 100000000
using namespace std;

int n,q,cnt,sumedge;
int w[maxn],size[maxn],deep[maxn],top[maxn],dad[maxn];
int re[maxn],head[maxn],tpos[maxn];

struct Tree{
    int l,r,sum,mx;
}tr[maxn<<2];

struct Edge{
    int x,y,nxt;
    Edge(int x=0,int y=0,int nxt=0):
        x(x),y(y),nxt(nxt){}
}edge[maxn<<1];

void add(int x,int y){
    edge[++sumedge]=Edge(x,y,head[x]);
    head[x]=sumedge;
}

void dfs(int x){
    size[x]=1;deep[x]=deep[dad[x]]+1;
    for(int i=head[x];i;i=edge[i].nxt){
        int v=edge[i].y;
        if(v==dad[x])continue;
        dad[v]=x;
        dfs(v);
        size[x]+=size[v];
    }
}

void dfs_(int x){
    tpos[x]=++cnt;re[cnt]=x;
    int s=0;
    if(!top[x])top[x]=x;
    for(int i=head[x];i;i=edge[i].nxt){
        int v=edge[i].y;
        if(v!=dad[x]&&size[v]>size[s])s=v;
    }
    if(s){
        top[s]=top[x];
        dfs_(s);
    }
    for(int i=head[x];i;i=edge[i].nxt){
        int v=edge[i].y;
        if(v!=dad[x]&&v!=s)dfs_(v);
    }
}

void pushup(int rt){
    tr[rt].sum=tr[rt<<1].sum+tr[rt<<1|1].sum;
    tr[rt].mx=max(tr[rt<<1].mx,tr[rt<<1|1].mx);
    return;
}

void build(int rt,int l,int r){
    tr[rt].l=l;tr[rt].r=r;
    if(l==r){
        tr[rt].sum=tr[rt].mx=w[re[l]];
        return;
    }
    int mid=(l+r)>>1;
    build(rt<<1,l,mid);build(rt<<1|1,mid+1,r);
    pushup(rt);
}

void update(int rt,int l,int r,int q,int v){
    if(l==r){
        tr[rt].sum=tr[rt].mx=v;
        return;
    }
    int mid=(l+r)>>1;
    if(q<=mid)update(rt<<1,l,mid,q,v);
    else update(rt<<1|1,mid+1,r,q,v);
    pushup(rt);
}

int querysum(int rt,int l,int r,int ql,int qr){
    if(ql<=l&&r<=qr)return tr[rt].sum;
    int mid=(l+r)>>1,ans=0;
    if(ql<=mid)ans+=querysum(rt<<1,l,mid,ql,qr);
    if(qr>mid)ans+=querysum(rt<<1|1,mid+1,r,ql,qr);
    return ans;
}

int querymax(int rt,int l,int r,int ql,int qr){
    if(ql<=l&&r<=qr)return tr[rt].mx;
    int mid=(l+r)>>1,ans=-inf;
    if(ql<=mid)ans=max(ans,querymax(rt<<1,l,mid,ql,qr));
    if(qr>mid)ans=max(ans,querymax(rt<<1|1,mid+1,r,ql,qr));
    return ans;
}

int qsum(int x,int y){
    int ans=0;
    while(top[x]!=top[y]){
        if(deep[top[x]]<deep[top[y]])swap(x,y);
        ans+=querysum(1,1,n,tpos[top[x]],tpos[x]);
        x=dad[top[x]];
    }
    if(deep[x]>deep[y])swap(x,y);
    ans+=querysum(1,1,n,tpos[x],tpos[y]);
    return ans;
}
int qmax(int x,int y){
    int ans=-inf;
    while(top[x]!=top[y]){
        if(deep[top[x]]<deep[top[y]])swap(x,y);
        ans=max(ans,querymax(1,1,n,tpos[top[x]],tpos[x]));
        x=dad[top[x]];
    }
    if(deep[x]>deep[y])swap(x,y);
    ans=max(ans,querymax(1,1,n,tpos[x],tpos[y]));
    return ans;
}

int main(){
    scanf("%d",&n);
    for(int i=1;i<n;i++){
        int x,y;
        scanf("%d%d",&x,&y);
        add(x,y);add(y,x);
    }
    for(int i=1;i<=n;i++)scanf("%d",&w[i]);
    dfs(1);dfs_(1);build(1,1,n);
    scanf("%d",&q);
    for(;q;q--){
        int x,y;char s[10];
        scanf("%s%d%d",s,&x,&y);
        if(s[1]=='H')update(1,1,n,tpos[x],y);
        if(s[1]=='M')printf("%d\n",qmax(x,y));
        if(s[1]=='S')printf("%d\n",qsum(x,y));
    }
    return 0;
}
AC

 

T4BZOJ4034树上操作

传送门

题目大意:区间修改 子树和 节点到根节点的路径权值和

代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#define maxn 500005
#define LL long long
using namespace std;

int sumedge,cnt,n,m;
int head[maxn],size[maxn],dad[maxn],deep[maxn],top[maxn];
int tpos[maxn],re[maxn],w[maxn];

struct Tree{
    int l,r;LL sum,s;
}tr[maxn<<2];

struct Edge{
    int x,y,nxt;
    Edge(int x=0,int y=0,int nxt=0):
        x(x),y(y),nxt(nxt){}
}edge[maxn<<1];


void read(int &x){
    char ch=getchar();x=0;int f=1;
    for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1;
    for(;isdigit(ch);ch=getchar())x=x*10+ch-'0';
    x=x*f;
}

void add(int x,int y){
    edge[++sumedge]=Edge(x,y,head[x]);
    head[x]=sumedge;
}

void dfs(int x){
    size[x]=1;deep[x]=deep[dad[x]]+1;
    for(int i=head[x];i;i=edge[i].nxt){
        int v=edge[i].y;
        if(v==dad[x])continue;
        dad[v]=x;dfs(v);
        size[x]+=size[v];
    }
}

void dfs_(int x){
    int s=0;tpos[x]=++cnt;re[cnt]=x;
    if(!top[x])top[x]=x;
    for(int i=head[x];i;i=edge[i].nxt){
        int v=edge[i].y;
        if(v!=dad[x]&&size[v]>size[s])s=v;
    }
    if(s){
        top[s]=top[x];
        dfs_(s);
    }
    for(int i=head[x];i;i=edge[i].nxt){
        int v=edge[i].y;
        if(v!=dad[x]&&v!=s)dfs_(v);
    }
}

void pushup(int rt){
    tr[rt].sum=tr[rt<<1].sum+tr[rt<<1|1].sum;
    return;
}

void pushdown(int rt){
    if(!tr[rt].s)return;
    tr[rt<<1].s+=tr[rt].s;tr[rt<<1|1].s+=tr[rt].s;
    tr[rt<<1].sum+=(LL)(tr[rt<<1].r-tr[rt<<1].l+1)*tr[rt].s;
    tr[rt<<1|1].sum+=(LL)(tr[rt<<1|1].r-tr[rt<<1|1].l+1)*tr[rt].s;
    tr[rt].s=0;return;
}

void build(int rt,int l,int r){
    tr[rt].l=l;tr[rt].r=r;
    if(l==r){
        tr[rt].sum=w[re[l]];
        return;
    }
    int mid=(l+r)>>1;
    build(rt<<1,l,mid);build(rt<<1|1,mid+1,r);
    pushup(rt);
}

void change(int rt,int l,int r,int ql,int qr,int p){
    if(l>=ql&&r<=qr){
        tr[rt].sum+=(LL)(r-l+1)*p;
        tr[rt].s+=p;
        return;
    }
    pushdown(rt);
    int mid=(l+r)>>1;
    if(ql<=mid)change(rt<<1,l,mid,ql,qr,p);
    if(qr>mid)change(rt<<1|1,mid+1,r,ql,qr,p);
    pushup(rt);
}

LL query_sum(int rt,int l,int r,int ql,int qr){
    if(l>=ql&&r<=qr){
        return tr[rt].sum;
    }
    pushdown(rt);
    int mid=(l+r)>>1;LL ans=0;
    if(ql<=mid)ans+=query_sum(rt<<1,l,mid,ql,qr);
    if(qr>mid)ans+=query_sum(rt<<1|1,mid+1,r,ql,qr);
    return ans;
}

LL query(int x){
    LL ret=0;
    for(;top[x]!=1;){
        ret+=query_sum(1,1,n,tpos[top[x]],tpos[x]);
        x=dad[top[x]];
    }
    ret+=query_sum(1,1,n,1,tpos[x]);
    return ret;
}

int main(){
    read(n);read(m);
    for(int i=1;i<=n;i++)read(w[i]);
    for(int i=1;i<n;i++){
        int x,y;
        read(x);read(y);
        add(x,y);add(y,x);
    }
    dfs(1);dfs_(1);build(1,1,n);
    for(int i=1;i<=m;i++){
        int od,x,a;
        read(od);read(x);
        if(od==1){
            read(a);
            change(1,1,n,tpos[x],tpos[x],a);
        }else if(od==2){
            read(a);
            change(1,1,n,tpos[x],tpos[x]+size[x]-1,a);
        }else if(od==3){
            printf("%lld\n",query(x));
        }
    }
    return 0;
}

AC
AC

 

 

T5BZOJ2243染色

传送门

题目大意:求a-b路径上有多少个颜色连续的序列

代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#define maxn 100009
using namespace std;

int n,m,cnt,sumedge;
int head[maxn],dad[maxn],size[maxn],deep[maxn],top[maxn];
int c[maxn],re[maxn],tpos[maxn];
char s[10];

struct Tree{
    int l,r,sum,lc,rc,s;
}tr[maxn<<2];

struct Edge{
    int x,y,nxt;
    Edge(int x=0,int y=0,int nxt=0):
        x(x),y(y),nxt(nxt){}
}edge[maxn<<1];

void add(int x,int y){
    edge[++sumedge]=Edge(x,y,head[x]);
    head[x]=sumedge;
}

void dfs(int x){
    size[x]=1;deep[x]=deep[dad[x]]+1;
    for(int i=head[x];i;i=edge[i].nxt){
        int v=edge[i].y;
        if(v==dad[x])continue;
        dad[v]=x;dfs(v);
        size[x]+=size[v];
    }
}

void dfs_(int x){
    int s=0;tpos[x]=++cnt;re[cnt]=x;
    if(!top[x])top[x]=x;
    for(int i=head[x];i;i=edge[i].nxt){
        int v=edge[i].y;
        if(v!=dad[x]&&size[v]>size[s])s=v;
    }
    if(s){
        top[s]=top[x];
        dfs_(s);
    }
    for(int i=head[x];i;i=edge[i].nxt){
        int v=edge[i].y;
        if(v!=dad[x]&&v!=s)dfs_(v);
    }
}

void pushup(int rt){
    tr[rt].sum=tr[rt<<1].sum+tr[rt<<1|1].sum-(tr[rt<<1].rc==tr[rt<<1|1].lc);
    tr[rt].lc=tr[rt<<1].lc;tr[rt].rc=tr[rt<<1|1].rc;
    return;
}

void pushdown(int rt){
    if(!tr[rt].s)return;
    tr[rt<<1].sum=tr[rt<<1|1].sum=1;
    tr[rt<<1].rc=tr[rt<<1].lc=tr[rt<<1|1].lc=tr[rt<<1|1].rc=tr[rt].s;
    tr[rt<<1].s=tr[rt<<1|1].s=tr[rt].s;
    tr[rt].s=0;return;
}

void build(int rt,int l,int r){
    tr[rt].l=l;tr[rt].r=r;
    if(l==r){
        tr[rt].sum=1;tr[rt].lc=tr[rt].rc=c[re[l]];
        return;
    }
    int mid=(l+r)>>1;
    build(rt<<1,l,mid);build(rt<<1|1,mid+1,r);
    pushup(rt);
}

void change(int rt,int l,int r,int ql,int qr,int p){
    if(l>=ql&&r<=qr){
        tr[rt].sum=1;tr[rt].lc=tr[rt].rc=p;tr[rt].s=p;
        return;
    }
    pushdown(rt);
    int mid=(l+r)>>1;
    if(ql<=mid)change(rt<<1,l,mid,ql,qr,p);
    if(qr>mid)change(rt<<1|1,mid+1,r,ql,qr,p);
    pushup(rt);
}

int query_sum(int rt,int l,int r,int ql,int qr){
    if(l>=ql&&r<=qr){
        return tr[rt].sum;
    }
    pushdown(rt);
    int mid=(l+r)>>1;
    if(qr<=mid)return query_sum(rt<<1,l,mid,ql,qr);
    if(ql>mid)return query_sum(rt<<1|1,mid+1,r,ql,qr);
    return query_sum(rt<<1,l,mid,ql,qr)+query_sum(rt<<1|1,mid+1,r,ql,qr)-(tr[rt<<1].rc==tr[rt<<1|1].lc);//**
}

int getcolr(int rt,int l,int r,int p){
    if(l==r)return tr[rt].lc;
    pushdown(rt);
    int mid=(l+r)>>1;
    if(p<=mid)return getcolr(rt<<1,l,mid,p);
    if(p>mid)return getcolr(rt<<1|1,mid+1,r,p);
}

int query(int x,int y){
    int ret=0;
    for(;top[x]!=top[y];){
        if(deep[top[x]]>deep[top[y]])swap(x,y);
        ret+=query_sum(1,1,n,tpos[top[y]],tpos[y]);
        if(getcolr(1,1,n,tpos[top[y]])==getcolr(1,1,n,tpos[dad[top[y]]]))ret--;
        y=dad[top[y]];
    }
    if(deep[x]>deep[y])swap(x,y);
    ret+=query_sum(1,1,n,tpos[x],tpos[y]);
    return ret;
}

void change_(int x,int y,int c){
    for(;top[x]!=top[y];){
        if(deep[top[x]]>deep[top[y]])swap(x,y);
        change(1,1,n,tpos[top[y]],tpos[y],c);
        y=dad[top[y]];
    }
    if(deep[x]>deep[y])swap(x,y);
    change(1,1,n,tpos[x],tpos[y],c);
}

int main(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)scanf("%d",&c[i]);
    for(int i=1;i<n;i++){
        int x,y;
        scanf("%d%d",&x,&y);
        add(x,y);add(y,x);
    }
    dfs(1);dfs_(1);build(1,1,n);
    for(int i=1;i<=m;i++){
        int x,y,z;
        scanf("%s",s);
        if(s[0]=='Q'){
            scanf("%d%d",&x,&y);
            printf("%d\n",query(x,y));
        }else  {
            scanf("%d%d%d",&x,&y,&z);
            change_(x,y,z);
        }
    }
    return 0;
}

AC
AC

 

 

T6BZOJ1984月下毛景树

题目大意:

Max x--y 树上x--y之间边的最大权值

Cover x--y w.树上x--y之前边的权值都变为w

Add x--y w 树上x--y之间边权都加w

Change x w把第x条边权值改为w

代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#define maxn 300009
using namespace std;

int n,m,cnt,sumedge;
int size[maxn],dad[maxn],deep[maxn],top[maxn],head[maxn];
int tpos[maxn],re[maxn],fe[maxn],st[maxn],ed[maxn];
char s[10];

struct Tree{
    int l,r,mx,adc,cvs;
}tr[maxn<<2];

struct Edge{
    int x,y,z,nxt;
    Edge(int x=0,int y=0,int z=0,int nxt=0):
        x(x),y(y),z(z),nxt(nxt){}
}edge[maxn<<1];

void add(int x,int y,int z){
    edge[++sumedge]=Edge(x,y,z,head[x]);
    head[x]=sumedge;
}

void dfs(int x){
    size[x]=1;deep[x]=deep[dad[x]]+1;
    for(int i=head[x];i;i=edge[i].nxt){
        int v=edge[i].y;
        if(v==dad[x])continue;
        dad[v]=x;fe[v]=edge[i].z;dfs(v);
        size[x]+=size[v];
    }
}

void dfs_(int x){
    int s=0;
    if(!top[x])top[x]=x;
    tpos[x]=++cnt;re[cnt]=x;
    for(int i=head[x];i;i=edge[i].nxt){
        int v=edge[i].y;
        if(v!=dad[x]&&size[v]>size[s])s=v;
    }
    if(s){
        top[s]=top[x];
        dfs_(s);
    }
    for(int i=head[x];i;i=edge[i].nxt){
        int v=edge[i].y;
        if(v!=dad[x]&&v!=s)dfs_(v);
    }
}

void pushup(int rt){
    tr[rt].mx=max(tr[rt<<1].mx,tr[rt<<1|1].mx);
    return;
}

void pushdown(int rt){
    if(tr[rt].cvs!=-1){
        tr[rt<<1].mx=tr[rt<<1|1].mx=tr[rt].cvs;
        tr[rt<<1].adc=tr[rt<<1|1].adc=0;
        tr[rt<<1].cvs=tr[rt<<1|1].cvs=tr[rt].cvs;
        tr[rt].cvs=-1;
    }
    if(tr[rt].adc){
        tr[rt<<1].mx+=tr[rt].adc;tr[rt<<1|1].mx+=tr[rt].adc;
        tr[rt<<1].adc+=tr[rt].adc;tr[rt<<1|1].adc+=tr[rt].adc;
        tr[rt].adc=0;
    }
}

void build(int rt,int l,int r){
    tr[rt].l=l;tr[rt].r=r;tr[rt].cvs=-1;
    if(l==r){
        tr[rt].mx=fe[re[l]];
        return;
    }
    int mid=(l+r)>>1;
    build(rt<<1,l,mid);build(rt<<1|1,mid+1,r);
    pushup(rt);
}
//-----------------------------------------------------
void change_Node(int rt,int l,int r,int p,int w){
    if(l==r){
        tr[rt].mx=w;
        return;
    }
    pushdown(rt);
    int mid=(l+r)>>1;
    if(p<=mid)change_Node(rt<<1,l,mid,p,w);
    if(p>mid)change_Node(rt<<1|1,mid+1,r,p,w);
    pushup(rt);
}

void change_node(int k,int w){
    int p,x,y;
    x=st[k];y=ed[k];p=dad[x]==y?x:y;
    change_Node(1,1,n,tpos[p],w);
}
//--------------------------------------------------------
void change_Cover(int rt,int l,int r,int ql,int qr,int w){
    if(l>=ql&&r<=qr){
        tr[rt].mx=w;tr[rt].cvs=w;tr[rt].adc=0;
        return;
    }
    pushdown(rt);
    int mid=(l+r)>>1;
    if(ql<=mid)change_Cover(rt<<1,l,mid,ql,qr,w);
    if(qr>mid)change_Cover(rt<<1|1,mid+1,r,ql,qr,w);
    pushup(rt);
}

void change_cover(int x,int y,int w){
    for(;top[x]!=top[y];){
        if(deep[top[x]]>deep[top[y]])swap(x,y);
        change_Cover(1,1,n,tpos[top[y]],tpos[y],w);
        y=dad[top[y]];
    }
    if(deep[x]>deep[y])swap(x,y);
    change_Cover(1,1,n,tpos[x]+1,tpos[y],w);
}
//---------------------------------------------------------
void change_Add(int rt,int l,int r,int ql,int qr,int w){
    if(l>=ql&&r<=qr){
        tr[rt].mx+=w;tr[rt].adc+=w;
        return;
    }
    pushdown(rt);
    int mid=(l+r)>>1;
    if(ql<=mid)change_Add(rt<<1,l,mid,ql,qr,w);
    if(qr>mid)change_Add(rt<<1|1,mid+1,r,ql,qr,w);
    pushup(rt);
}

void change_add(int x,int y,int w){
    for(;top[x]!=top[y];){
        if(deep[top[x]]>deep[top[y]])swap(x,y);
        change_Add(1,1,n,tpos[top[y]],tpos[y],w);
        y=dad[top[y]];
    }
    if(deep[x]>deep[y])swap(x,y);
    change_Add(1,1,n,tpos[x]+1,tpos[y],w);
}
//-----------------------------------------------------------
int query_mx(int rt,int l,int r,int ql,int qr){
    if(l>=ql&&r<=qr){
        return tr[rt].mx;
    }
    pushdown(rt);
    int mid=(l+r)>>1,ret=-1;
    if(ql<=mid)ret=max(ret,query_mx(rt<<1,l,mid,ql,qr));
    if(qr>mid)ret=max(ret,query_mx(rt<<1|1,mid+1,r,ql,qr));
    return ret;
}

int query(int x,int y){
    int ans=-1;
    for(;top[x]!=top[y];){
        if(deep[top[x]]>deep[top[y]])swap(x,y);
        ans=max(ans,query_mx(1,1,n,tpos[top[y]],tpos[y]));
        y=dad[top[y]];
    }
    if(deep[x]>deep[y])swap(x,y);
    ans=max(ans,query_mx(1,1,n,tpos[x]+1,tpos[y]));
    return ans;
}
//------------------------------------------------------------
int main(){
    scanf("%d",&n);
    for(int i=1;i<n;i++){
        int z;
        scanf("%d%d%d",&st[i],&ed[i],&z);
        add(st[i],ed[i],z);add(ed[i],st[i],z);
    }
    dfs(1);dfs_(1);build(1,1,n);
    while(1){
        int x,y,z;
        scanf("%s",s);
        if(s[0]=='S')break;
        if(s[1]=='h'){
            scanf("%d%d",&x,&z);                                                            
            change_node(x,z);
        }else if(s[1]=='o'){
            scanf("%d%d%d",&x,&y,&z);
            change_cover(x,y,z);
        }else if(s[1]=='d'){
            scanf("%d%d%d",&x,&y,&z);
            change_add(x,y,z);
        }else if(s[2]=='x'){
            scanf("%d%d",&x,&y);
            printf("%d\n",query(x,y));
        }
    }
    return 0;
}

AC
AC

 

posted @ 2017-10-21 10:58  ANhour  阅读(329)  评论(0编辑  收藏  举报