bzoj2631 tree

也算填了一個坑吧。。。以前用線段樹就不會搞這個混合加乘的操作。。。

而且都開long long 就超時了,換成unsigned int

/**************************************************************
    Problem: 2631
    User: Clare
    Language: C++
    Result: Accepted
    Time:16420 ms
    Memory:5016 kb
****************************************************************/
 
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <queue>
#include <stack>
#include <vector>
using namespace std;
 
#define N 100010
#define INF 0x7fffffff
#define Mod 51061
typedef unsigned int ll;
 
int n,m,q;
int fa[N],c[N][2],next[N],size[N];
ll sum[N],v[N],flag[N],flag1[N];
bool Rev[N];
char S[5];
stack<int> st;
 
inline int read()
{
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch<='9'&&ch>='0'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
 
bool Pd_root(int k)
{
    return !(c[fa[k]][0]==k)&&!(c[fa[k]][1]==k);
}
 
void Pushup(int k)
{
    int l=c[k][0],r=c[k][1];
    size[k]=size[l]+size[r]+1;
    sum[k]=(sum[r]+sum[l]+v[k])%Mod;
}
 
void Cal(int k,ll mul,ll add)
{
    if(!k)
        return;
    v[k]=(v[k]*mul+add)%Mod;
    sum[k]=(sum[k]*mul+add*size[k])%Mod;
    flag[k]=flag[k]*mul%Mod;
    flag1[k]=(flag1[k]*mul+add)%Mod;
}
 
void Pushdown(int k)
{
    int l=c[k][0],r=c[k][1];
    if(Rev[k])
    {
        Rev[k]^=1;Rev[r]^=1;Rev[l]^=1;
        swap(c[k][0],c[k][1]);
    }
    Cal(l,flag[k],flag1[k]);
    Cal(r,flag[k],flag1[k]);
    flag[k]=1;flag1[k]=0;
}
 
void Rotate(int x)
{
    int y=fa[x],z=fa[y],l,r;
    if(c[y][0]==x)l=0;else l=1;r=l^1;
    if(Pd_root(y));
    else if(c[z][0]==y)c[z][0]=x;
    else c[z][1]=x;
    fa[x]=z;fa[y]=x;fa[c[x][r]]=y;
    c[y][l]=c[x][r];c[x][r]=y;
    Pushup(y);Pushup(x);
}
 
void Splay(int x)
{
    int i=x;
    for(i=x;!Pd_root(i);i=fa[i])
        st.push(i);
    st.push(i);
    while(!st.empty())
    {
        int now=st.top();st.pop();
        Pushdown(now);
    }
    while(!Pd_root(x))
    {
        int y=fa[x],z=fa[y];
        if(!Pd_root(y))
        {
            if(c[z][0]==y^c[y][0]==x)
                Rotate(x);
            else Rotate(y);
        }
        Rotate(x);
    }
}
 
void Access(int x)
{
    for(int t=0;x;t=x,x=fa[x])
        Splay(x),c[x][1]=t,Pushup(x);
}
 
void Move_to_root(int x)
{
    Access(x);Splay(x);Rev[x]^=1;
}
 
void Join(int x,int y)
{
    Move_to_root(x);fa[x]=y;Splay(x);
}
 
void Cut(int x,int y)
{
    Move_to_root(x);Access(y);Splay(y);
    if(x==c[y][0])
        c[y][0]=fa[x]=0;
    else c[y][1]=fa[x]=0;
    Pushup(y);Pushup(x);
}
 
void Split(int x,int y)
{
    Move_to_root(x);Access(y);Splay(y);
}
 
int main()
{
    n=read();q=read();
    for(int i=1;i<=n;i++)
        v[i]=sum[i]=size[i]=flag[i]=1;
    for(int i=1;i<=n-1;i++)
    {
        int x=read(),y=read();
        Join(x,y);
    }
    while(q--)
    {
        scanf("%s",S);
        if(S[0]=='+')
        {
            int x=read(),y=read(),val=read();
            Split(x,y);Cal(y,1,val);
        }
        else if(S[0]=='*')
        {
            int x=read(),y=read(),val=read();
            Split(x,y);Cal(y,val,0);
        }
        else if(S[0]=='-')
        {
            int x1=read(),y1=read(),x2=read(),y2=read();
            Cut(x1,y1);Join(x2,y2);
        }
        else
        {
            int x=read(),y=read();
            Split(x,y);
            printf("%d\n",sum[y]);
        }
    }
    return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章