【BZOJ2814】tree

Description

给出一棵N 个点的树,每个点有两层,每层有权值和颜色(黑白) 。要求支持以下操作。
1. Cover s t color 将s到t的路径上的点的两层的颜色全部置为 color(0 白1 黑)
2. CVal index layer val 将index号点的 layer 层的权值修改为 val
3. CColor index layer color 将 index号点的 layer 层的颜色修改为 color
4. QMax s t 询问s到 t的路径上的白色最大权值和路径的权值(任意白色层为起点,每次只能往相同点不同层或者相邻点同一层上移动,每个点的每一层最多走一次,路径经过的层必须都是白色) ,若 s到 t上的路径没有白点则输出[Bad Request.]
5. QLen s t 询问s到t的路径上的白色最大权值和路径的长度,若 s到 t的路径上没有白点则输出 0
初始树上权值均为 1,颜色均为白色。
N<=5W,Q<=5W,1<=val<=1K,0<=color,layer<=1 所有数据不超过longint范围。 .
对于40%的分数,没有 1,5 号操作,N,Q <= 1K
对于80%的分数,没有 5号操作
Input

第一行一个数 N,接下来N*2-2 个数 s,t,代表 s与t之间有连边。第N+1行一个数 Q,
表示操作数。接下来Q 行每行一个操作。
Output

对于每次 QMax,QLen输出对应答案,用换行符分隔。
Sample Input

6

1 2 2 4 2 5 1 3 3 6

7

CVal 1 0 5

CVal 1 1 3

CColor 1 0 1

CVal 2 0 5

CVal 3 0 3

QMax 5 6

QLen 5 6

Sample Output

17

9
HINT

Source

人生成就,写过最长的码农题
半天写代码,半天调代码
LCT大法好啊,比链剖看着美观多了QwQ

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#define MAXN 50010
#define GET (ch >= '0' && ch <= '9')
#define MAXINT 0x3f3f3f3f
using namespace std;
int n,m;
int sta[MAXN],top;
char ch[8];
inline void in(int &x)
{
    char ch = getchar() ; x = 0;
    while (!GET)    ch = getchar();
    while (GET) x = x * 10 + ch - '0' , ch = getchar();
}





//节点颜色 1为白色 0为黑色 





//Data Transmit 
inline void update(int &a,int &b,int c,int d)
{
    if (a < c)  a = c , b = d;
    else    if (a == c && b < d)    b = d;
}





//Define Information Node 
struct treenode
{
    int len1[2][2],len2[2][2];  
    int val1[2][2],val2[2][2];
    int llen[2],rlen[2];
    int lval[2],rval[2];
    int minn[2][2];  
    int size,sum;
    int maxl,maxv;
    treenode()
    {
        for (int i = 0 ; i <= 1 ; i++)  lval[i] = rval[i] = llen[i] = rlen[i] = -MAXINT;
        maxl = maxv = -MAXINT , size = sum = 0;
        for (int i = 0 ; i <= 1 ; i++)  for (int j = 0 ; j <= 1 ; j++)
            len1[i][j] = len2[i][j] = val1[i][j] = val2[i][j] = -MAXINT,
            minn[i][j] = MAXINT;
    }
    //Node Union 
    inline friend treenode operator + (const treenode& a,const treenode& b)
    {
        treenode ret;
        for (int i = 0 ; i <= 1 ; i++)  for (int j = 0 ; j <= 1 ; j++)  //floyed 
        {
            for (int k = 0 ; k <= 1 ; k++)
                update(ret.val1[i][j] , ret.len1[i][j] , a.val1[i][k] + b.val1[k][j] , a.len1[i][k] + b.len1[k][j]),
                update(ret.val2[i][j] , ret.len2[i][j] , a.val2[i][k] + b.val2[k][j] , a.len2[i][k]+b.len2[k][j]),
                update(ret.lval[i] , ret.llen[i] , a.val1[i][k] + b.lval[k] , a.len1[i][k] + b.llen[k]),
                update(ret.rval[j] , ret.rlen[j] , a.rval[k] + b.val2[j][k] , a.rlen[k] + b.len2[k][j]),
                ret.minn[i][j] = min(ret.minn[i][j] , min(a.minn[i][k] , b.minn[k][j]));
            update(ret.lval[i] , ret.llen[i] , a.lval[i] , a.llen[i]);
            update(ret.rval[j] , ret.rlen[j] , b.rval[j] , b.rlen[j]);
        }
        update(ret.maxv , ret.maxl , a.maxv , a.maxl);
        update(ret.maxv , ret.maxl , b.maxv , b.maxl);
        for (int i = 0 ; i <= 1 ; i++)  update(ret.maxv , ret.maxl , a.rval[i] + b.lval[i] , a.rlen[i] + b.llen[i]);
        ret.size = a.size + b.size ; ret.sum = a.sum + b.sum;
        return ret;
    }
};





//Define LCT 
struct splay
{
    int ch[2],fa,val[2];
    bool flag,cov,col[2];
    treenode w;
}tree[MAXN];





//Get Node 
inline treenode findnode(int x)
{
    treenode ret ; ret.size = 2 ; ret.sum = tree[x].val[0] + tree[x].val[1];
    for (int i = 0 ; i <= 1 ; i++)  for (int j = 0 ; j <= 1 ; j++)  
    {
        ret.minn[i][j] = min(tree[x].val[i] , tree[x].val[j]);
        if (tree[x].col[i] && tree[x].col[j])
        {
            ret.len1[i][j] = ret.len2[i][j] = (i == j ? 1 : 2),
            ret.val1[i][j] = ret.val2[i][j] = (i == j ? tree[x].val[i] : tree[x].val[i] + tree[x].val[j]);
            update(ret.maxv , ret.maxl , ret.val1[i][j] , ret.len1[i][j]),
            update(ret.lval[i] , ret.llen[i] , ret.val1[i][j] , ret.len1[i][j]),
            update(ret.rval[j] , ret.rlen[j] , ret.val2[i][j] , ret.len2[i][j]);
        }
    }
    return ret;
}





//Information Update 
inline void push_up(int x)
{
    if (!x) return;
    tree[x].w = findnode(x);
    if (tree[x].ch[0])  tree[x].w = tree[tree[x].ch[0]].w + tree[x].w;
    if (tree[x].ch[1])  tree[x].w = tree[x].w + tree[tree[x].ch[1]].w;
}
inline void Cover(int x,bool col)
{
    treenode ret;
    tree[x].flag = 1 , tree[x].cov = col;
    tree[x].col[0] = tree[x].col[1] = col;
    if (col)
    {
        if ((tree[x].w.size >> 1) & 1)
        {
            for (int i = 0 ; i <= 1 ; i++)  for (int j = 0 ; j <= 1 ; j++)
                if (i != j)
                    ret.len1[i][j] = ret.len2[i][j] = tree[x].w.size,
                    ret.val1[i][j] = ret.val2[i][j] = tree[x].w.sum;
                else
                    ret.len1[i][j] = ret.len2[i][j] = tree[x].w.size - 1,
                    ret.val1[i][j] = ret.val2[i][j] = tree[x].w.sum - tree[x].w.minn[i][j];
        }
        else
        {
            for (int i = 0 ; i <= 1 ; i++)  for (int j = 0 ; j <= 1 ; j++)
                if (i == j)
                    ret.len1[i][j] = ret.len2[i][j] = tree[x].w.size,
                    ret.val1[i][j] = ret.val2[i][j] = tree[x].w.sum;
                else
                    ret.len1[i][j] = ret.len2[i][j] = tree[x].w.size - 1,
                    ret.val1[i][j] = ret.val2[i][j] = tree[x].w.sum - tree[x].w.minn[i][j];

        }
        ret.maxl = tree[x].w.size ; ret.maxv = tree[x].w.sum;
        for (int i = 0 ; i <= 1 ;i++)
            ret.llen[i] = ret.rlen[i] = tree[x].w.size,
            ret.lval[i] = ret.rval[i] = tree[x].w.sum;
    }
    ret.size = tree[x].w.size ; ret.sum = tree[x].w.sum;
    for (int i = 0 ; i <= 1 ; i++)  for (int j = 0 ; j <= 1 ; j++)  ret.minn[i][j] = tree[x].w.minn[i][j];
    tree[x].w = ret;
}
inline void push_down(int x)
{
    if (!x) return;
    if (tree[x].flag)
    {
        if (tree[x].ch[0])  Cover(tree[x].ch[0] , tree[x].cov);
        if (tree[x].ch[1])  Cover(tree[x].ch[1] , tree[x].cov);
        tree[x].flag = 0 ; tree[x].cov = 0;
    }
}





//LCT Operation 
inline bool is_root(int x)  {   return tree[tree[x].fa].ch[0] != x && tree[tree[x].fa].ch[1] != x;  }
inline void rot(int x)
{
    int y = tree[x].fa,z = tree[y].fa,l,r;
    l = (tree[y].ch[1] == x) ; r = l ^ 1;
    if (!is_root(y))    tree[z].ch[tree[z].ch[1] == y] = x;
    tree[x].fa = z;tree[y].fa = x ; tree[tree[x].ch[r]].fa = y;
    tree[y].ch[l] = tree[x].ch[r] ; tree[x].ch[r] = y;
    push_up(y) ; push_up(x);
}
inline void Splay(int x)
{
    sta[++top] = x;
    for (int i = x ; !is_root(i) ; i = tree[i].fa)  sta[++top] = tree[i].fa;
    while (top) push_down(sta[top--]);
    while (!is_root(x))
    {
        int y = tree[x].fa , z = tree[y].fa;
        if (!is_root(y))
        {
            if ((tree[z].ch[0] == y) ^ (tree[y].ch[0] == x))    rot(x);
            else    rot(y);
        }
        rot(x);
    }
}
inline void access(int x)   {   for (int i = 0 ; x ; i = x , x = tree[x].fa)    Splay(x) , tree[x].ch[1] = i , push_up(x);  }





//Paint Color (Operation No.1)
inline void Set_color(int s,int t,bool col)
{
    access(s);
    for (int x = t , i = 0 ; x ; i = x , x = tree[x].fa)
    {
        Splay(x);
        if (!tree[x].fa)
        {
            tree[x].col[0] = tree[x].col[1] = col;
            if (tree[x].ch[1])  Cover(tree[x].ch[1] , col);
            if (i)  Cover(i , col);
        }
        tree[x].ch[1] = i ; push_up(x);
    }
}






//Node Modify (Operation No.2/3)  
inline void modify_val(int x,int y,int z)   {   Splay(x) ; tree[x].val[y] = z ; push_up(x); }
inline void modify_col(int x,int y,bool z)  {   Splay(x) ; tree[x].col[y] = z ; push_up(x); }






//Query (Operation 4/5) 
inline treenode query(int s,int t)
{
    access(s);
    for (int x = t , i = 0 ; x ; i = x , x = tree[x].fa)
    {
        Splay(x);
        if (!tree[x].fa)
        {
            treenode ret = findnode(x);
            if (tree[x].ch[1])
            {
                treenode tmp = tree[tree[x].ch[1]].w;
                for (int i = 0 ; i <= 1 ; i++)  for (int j = 0 ; j <= 1 ; j++)
                    swap(tmp.len1[i][j] , tmp.len2[i][j]),
                    swap(tmp.val1[i][j] , tmp.val2[i][j]);
                for (int i = 0 ; i <= 1 ; i++)  swap(tmp.llen[i] , tmp.rlen[i]) , swap(tmp.lval[i] , tmp.rval[i]);
                ret = tmp + ret;
            }
            if (i)  ret = ret + tree[i].w;
            return ret;
        }
        tree[x].ch[1] = i ; push_up(x);
    }
}





//initialization  
inline void init()
{
    for (int i = 1 ; i <= n ; i++)
    {
        for (int j = 0 ; j <= 1 ; j++)  tree[i].val[j] = tree[i].col[j] = 1;
        tree[i].w = findnode(i);
    }
}





//DFS build Tree 
int Top;
struct edge
{
    int to;
    edge *next;
}e[MAXN<<1],*prev[MAXN];
void insert(int u,int v)    {   e[++Top].to = v ; e[Top].next = prev[u] ; prev[u] = &e[Top];    }
void dfs(int x,int f)
{
    tree[x].fa = f;
    for (edge *i = prev[x] ; i ; i = i->next)
        if (i->to != f) 
        {
            if (!tree[x].ch[1]) tree[x].ch[1] = i->to;
            dfs(i->to , x);
        }
}





//debug
void printnode(treenode x)
{
    for (int i = 0 ; i <= 1 ; i++)  for (int j = 0 ; j <= 1 ; j++)  printf("%d ",x.val1[i][j]);
    for (int i = 0 ; i <= 1 ; i++)  for (int j = 0 ; j <= 1 ; j++)  printf("%d ",x.val2[i][j]);
    printf("\n");
    for (int i = 0 ; i <= 1 ; i++)  for (int j = 0 ; j <= 1 ; j++)  printf("%d ",x.len1[i][j]);
    for (int i = 0 ; i <= 1 ; i++)  for (int j = 0 ; j <= 1 ; j++)  printf("%d ",x.len2[i][j]);
    printf("\n");
    for (int i = 0 ; i <= 1 ; i++)  printf("%d ",x.llen[i]);
    for (int i = 0 ; i <= 1 ; i++)  printf("%d ",x.rlen[i]);
    printf("\n");
    for (int i = 0 ; i <= 1 ; i++)  printf("%d ",x.lval[i]);
    for (int i = 0 ; i <= 1 ; i++)  printf("%d ",x.rval[i]);
    printf("\n");
    for (int i = 0 ; i <= 1 ; i++)  for (int j = 0 ; j <= 1 ; j++)  printf("%d ",x.minn[i][j]);
    printf("\n");
    printf("%d %d %d %d\n",x.size , x.sum , x.maxl , x.maxv);
}
void print(int x)
{
    printf("%d\n" , x);
    printf("%d %d %d %d %d %d %d %d %d\n" , tree[x].ch[0] , tree[x].ch[1] , tree[x].fa , tree[x].val[0] , tree[x].val[1] , tree[x].flag , tree[x].cov , tree[x].col[0] , tree[x].col[1]);
    printnode(tree[x].w);
}






int main()
{
    in(n) ; int u,v,w ; init() ;
    for (int i = 1 ; i < n ; i++)   in(u) , in(v) , insert(u , v) , insert(v , u);
    dfs(1 , 0);
    for (int i = 1 ; i <= n ; i++)  if (!tree[i].ch[1]) Splay(i);
    for (in(m) ; m ; m--)
    {
        scanf("%s",ch);
        if (ch[1] == 'o')   in(u) , in(v) , in(w) , Set_color(u , v , w ^ 1);
        if (ch[1] == 'V')   in(u) , in(v) , in(w) , modify_val(u , v , w);
        if (ch[1] == 'C')   in(u) , in(v) , in(w) , modify_col(u , v , w ^ 1);
        if (ch[1] == 'M')
        {
            in(u) , in(v) ; treenode ans = query(u , v);
            if (ans.maxv < 0)   puts("Bad Request.");
            else    printf("%d\n" , ans.maxv);
        }
        if (ch[1] == 'L')
        {
            in(u) , in(v) ; treenode ans = query(u , v);
            printf("%d\n" , max(ans.maxl , 0));
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值