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));
}
}
}