您的位置:首页 > 其它

【BZOJ2814】tree

2016-02-15 11:16 393 查看
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));
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  LCT