BZOJ2631 tree

AC通道:http://www.lydsy.com/JudgeOnline/problem.php?id=2631

 

[分析]

  这题共有几种操作,很多种都是与路径有关的,还有一种就是断开与连接边.

  路径有关,而且树的形态也可以改变...这不就是动态树了么...

  这题中有两个tag,注意一下它们的优先顺序.怎么使得意义不会变呢?

  1.当下乘标记的时候,如果这里有加标记,注意将加标记也乘上这个数;加标记时直接加即可,不用管乘标记

  2.当下传标记时,先下传乘标记,再下传加标记.

  那就比较简单的解决了...

  

  [p.s.]因为这题有乘法,所以int是不能过的,如果是longlong似乎又会超时?...

  于是hzwer用了unsigned int 过了?...那我们也用unsigned int 吧...

  

  献上代码:

#include<cstdio>
#include<algorithm>

using namespace std;

typedef unsigned int ll;

const int mod=51061;
const int maxn=100010;

struct Node{
    int l,r,f,sz;
    ll dt,sm;
    ll js,cs;
    bool rt,rv;
    
    bool rev(){swap(l,r);}
}s[maxn];

int n,m;

inline int in(){
    int x=0;char ch=getchar();
    while(ch>'9' || ch<'0') ch=getchar();
    while(ch>='0' && ch<='9') x=x*10+ch-'0',ch=getchar();
    return x;
}

inline void add(ll &x,ll y){x+=y;if(x>=mod) x-=mod;}
inline void mul(ll &x,ll y){x=x*y%mod;}
inline ll remul(ll x,ll y){return x*y%mod;}
inline ll readd(ll x,ll y,ll z){return (x+y+z)%mod;}

void push_down(int x){
    if(s[x].rv){
        s[x].rev();s[x].rv=0;
        if(s[x].l) s[s[x].l].rv^=1;
        if(s[x].r) s[s[x].r].rv^=1;
    }
    int ls=s[x].l,rs=s[x].r,js=s[x].js,cs=s[x].cs;
    if(cs!=1){
        if(ls) mul(s[ls].sm,cs),mul(s[ls].cs,cs),mul(s[ls].dt,cs),mul(s[ls].js,cs);
        if(rs) mul(s[rs].sm,cs),mul(s[rs].cs,cs),mul(s[rs].dt,cs),mul(s[rs].js,cs);
        s[x].cs=1;
    }
    if(js){
        if(ls) add(s[ls].sm,remul(s[ls].sz,js)),add(s[ls].js,js),add(s[ls].dt,js);
        if(rs) add(s[rs].sm,remul(s[rs].sz,js)),add(s[rs].js,js),add(s[rs].dt,js);
        s[x].js=0;
    }
}

void down_tag(int x){
    if(s[x].f) down_tag(s[x].f);
    push_down(x);
}

void update(int x){
    s[x].sz=s[s[x].l].sz+s[s[x].r].sz+1;
    s[x].sm=readd(s[s[x].l].sm,s[s[x].r].sm,s[x].dt);
}

void zig(int x){
    int y=s[x].f;s[x].f=s[y].f;
    if(s[y].rt) s[y].rt=false,s[x].rt=true;
    else{ if(y==s[s[y].f].l) s[s[y].f].l=x;
        else s[s[y].f].r=x;}
    s[y].l=s[x].r;
    if(s[x].r) s[s[x].r].f=y;
    s[x].r=y,s[y].f=x;
    update(y);
}

void zag(int x){
    int y=s[x].f;s[x].f=s[y].f;
    if(s[y].rt) s[y].rt=false,s[x].rt=true;
    else{ if(y==s[s[y].f].l) s[s[y].f].l=x;
        else s[s[y].f].r=x;}
    s[y].r=s[x].l;
    if(s[x].l) s[s[x].l].f=y;
    s[x].l=y,s[y].f=x;
    update(y);
}

void Splay(int x){
    down_tag(x);
    int y;
    while(!s[x].rt){
        y=s[x].f;
        if(s[y].rt){ if(x==s[y].l) zig(x);
            else zag(x);}
        else{
            int z=s[y].f;
            if(y==s[z].l){ if(x==s[y].l) zig(y),zig(x);
                else zag(x),zig(x);}
            else{ if(x==s[y].r) zag(y),zag(x);
                else zig(x),zag(x);}
        }
    }
    update(x);
}

void Access(int x){
    for(int last=0;x;x=s[last=x].f){
        Splay(x);
        s[s[x].r].rt=true;
        s[s[x].r=last].rt=false;
        update(x);
    }
}

void make_rt(int x){
    Access(x);Splay(x);s[x].rv^=1;}

void Link(int v,int u){
    make_rt(u); s[u].f=v;
}

void Cut(int v,int u){
    make_rt(u); Access(v); Splay(v);
    s[u].f=s[v].f;
    s[u].rt=true;
    s[v].f=s[v].l=0;
    update(v);
}

void Add(int y,int x,int k){
    make_rt(x); Access(y); Splay(y);
    add(s[y].dt,k),add(s[y].js,k);
    add(s[y].sm,remul(s[y].sz,k));
}

void Mul(int y,int x,int k){
    make_rt(x); Access(y); Splay(y);
    mul(s[y].dt,k),mul(s[y].cs,k);
    mul(s[y].sm,k),mul(s[y].js,k);
}

ll query(int y,int x){
    make_rt(x); Access(y); Splay(y);
    return s[y].sm;
}

int main(){
#ifndef ONLINE_JUDGE
    freopen("2631.in","r",stdin);
    freopen("2631.out","w",stdout);
#endif

    int u,v,c,u1,v1;
    char ord[2];
    
    n=in();m=in();
    for(int i=1;i<=n;i++) s[i].rt=s[i].dt=1;
    for(int i=1;i<n;i++)
        u=in(),v=in(),Link(u,v);
    
    while(m--){
        scanf("%s",ord),u=in(),v=in();
        if(ord[0]=='+')
            c=in(),Add(u,v,c);
        else if(ord[0]=='-')
            u1=in(),v1=in(),Cut(u,v),Link(u1,v1);
        else if(ord[0]=='*')
            c=in(),Mul(u,v,c);
        else
            printf("%d\n",query(u,v));
    }
    
    return 0;
}
View Code

 

posted @ 2016-01-16 14:05  诚叙  阅读(260)  评论(0编辑  收藏  举报