类似最大子段和去搞 可以把两头看成各有两个接口 然后随意维护十几个值搞搞搞
打了一中午 调了一晚上 发现看错题 改了改 调到睡觉
心累
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cstring>
using namespace std;
typedef long long ll;
inline char nc(){
static char buf[100000],*p1=buf,*p2=buf;
if (p1==p2) { p2=(p1=buf)+fread(buf,1,100000,stdin); if (p1==p2) return EOF; }
return *p1++;
}
inline void read(int &x){
char c=nc(),b=1;
for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1;
for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b;
}
inline void read(char *s){
char c=nc(); int len=0;
for (;!(c>='A' && c<='Z');c=nc());
for (;(c>='A' && c<='Z') || (c>='a' && c<='z');s[++len]=c,c=nc()); s[++len]=0;
}
const int N=50005;
struct abcd{
ll val; int len; int nil;
abcd() { nil=1; }
abcd(ll val,int len):val(val),len(len),nil(0) { }
friend abcd operator + (abcd A,abcd B){
if (A.nil) return B;
if (B.nil) return A;
return abcd(A.val+B.val,A.len+B.len);
}
bool operator < (const abcd &B) const{
if (B.nil) return 0;
if (nil) return 1;
return val==B.val?len<B.len:val<B.val;
}
};
struct data{
abcd ans,maxv[2][2],lmax[2],rmax[2]; int nil;
data() { nil=1; maxv[0][0]=maxv[1][1]=maxv[0][1]=maxv[1][0]=abcd();}
void rev(){
swap(maxv[1][0],maxv[0][1]);
swap(lmax[0],rmax[0]); swap(lmax[1],rmax[1]);
}
friend data operator + (data A,data B){
if (A.nil) return B;
if (B.nil) return A;
data ret; ret.nil=0;
for (int i=0;i<2;i++)
for (int j=0;j<2;j++)
for (int k=0;k<2;k++)
ret.maxv[i][j]=max(ret.maxv[i][j],A.maxv[i][k]+B.maxv[k][j]);
for (int i=0;i<2;i++){
ret.lmax[i]=A.lmax[i];
for (int j=0;j<2;j++)
ret.lmax[i]=max(ret.lmax[i],A.maxv[i][j]+B.lmax[j]);
}
for (int i=0;i<2;i++){
ret.rmax[i]=B.rmax[i];
for (int j=0;j<2;j++)
ret.rmax[i]=max(ret.rmax[i],A.rmax[j]+B.maxv[j][i]);
}
ret.ans=max(A.ans,B.ans);
for (int i=0;i<2;i++)
ret.ans=max(ret.ans,A.rmax[i]+B.lmax[i]);
return ret;
}
};
struct SEG{
struct node{
int len,sum,tag; int c[2];
data D; ll minv[2];
node(){
len=sum=0;
D.nil=1; minv[0]=minv[1]=1LL<<40;
tag=-1;
}
node(ll v0,ll v1,int c0,int c1){
len=1; tag=-1; c[0]=c0; c[1]=c1;
sum=v0+v1; minv[1]=v0; minv[0]=v1;
if (c0==1) v0=-1LL<<40;
if (c1==1) v1=-1LL<<40;
D.nil=0;
D.maxv[0][1]=D.maxv[1][0]=abcd(v0+v1,2);
D.maxv[0][0]=abcd(v0,1); D.maxv[1][1]=abcd(v1,1);
D.ans=max(max(abcd(v0,1),abcd(v1,1)),abcd(v0+v1,2));
D.lmax[0]=D.rmax[0]=max(abcd(v0,1),abcd(v0+v1,2));
D.lmax[1]=D.rmax[1]=max(abcd(v1,1),abcd(v0+v1,2));
}
void cover(int cc){
if (cc==0){
if (~len&1){
D.maxv[0][0]=D.maxv[1][1]=abcd(sum,len<<1);
D.maxv[0][1]=abcd(sum-minv[0],(len<<1)-1);
D.maxv[1][0]=abcd(sum-minv[1],(len<<1)-1);
}
else{
D.maxv[1][0]=D.maxv[0][1]=abcd(sum,len<<1);
D.maxv[0][0]=abcd(sum-minv[0],(len<<1)-1);
D.maxv[1][1]=abcd(sum-minv[1],(len<<1)-1);
}
D.lmax[0]=D.lmax[1]=D.rmax[0]=D.rmax[1]=D.ans=abcd(sum,len<<1);
}else{
D.maxv[0][0]=D.maxv[1][1]=D.maxv[0][1]=D.maxv[1][0]=abcd(-1LL<<40,0);
D.lmax[0]=D.lmax[1]=D.rmax[0]=D.rmax[1]=D.ans=abcd(-1LL<<40,0);
}
tag=cc; c[0]=c[1]=cc;
}
friend node operator + (const node &A,const node &B){
node ret;
ret.len=A.len+B.len;
ret.sum=A.sum+B.sum;
for (int i=0;i<2;i++)
ret.minv[i]=min(A.minv[i],B.minv[i^(A.len&1)]);
ret.D=A.D+B.D;
return ret;
}
}T[N<<2];
int M,TH;
void Build(int n){
for (M=1,TH=0;M<n+2;M<<=1,TH++);
for (int i=1;i<=n;i++)
T[M+i]=node(1,1,0,0);
for (int i=M-1;i;i--)
T[i]=T[i<<1]+T[i<<1|1];
}
void Pushdown(int rt){
int p;
for (int i=TH;i;i--)
if (T[p=rt>>i].tag!=-1)
{
T[p<<1].cover(T[p].tag); T[p<<1|1].cover(T[p].tag);
T[p].tag=-1;
}
}
void CVal(int s,int v0,int v1){
Pushdown(s+=M);
T[s]=node(v0,v1,T[s].c[0],T[s].c[1]);
while (s>>=1)
T[s]=T[s<<1]+T[s<<1|1];
}
void CColor(int s,int p,int c,int v0,int v1){
Pushdown(s+=M);
if (p==0)
T[s]=node(v0,v1,c,T[s].c[1]);
else
T[s]=node(v0,v1,T[s].c[0],c);
while (s>>=1)
T[s]=T[s<<1]+T[s<<1|1];
}
void Cover(int s,int t,int cc){
for (Pushdown(s+=M-1),Pushdown(t+=M+1);s^t^1;){
if (~s&1) T[s^1].cover(cc);
if ( t&1) T[t^1].cover(cc);
T[s>>=1]=T[s<<1]+T[s<<1|1];
T[t>>=1]=T[t<<1]+T[t<<1|1];
}
while (s>>=1)
T[s]=T[s<<1]+T[s<<1|1];
}
data Sum(int s,int t){
data lret,rret;
for (Pushdown(s+=M-1),Pushdown(t+=M+1);s^t^1;s>>=1,t>>=1){
if (~s&1) lret=lret+T[s^1].D;
if ( t&1) rret=T[t^1].D+rret;
}
return lret+rret;
}
}Seg;
struct edge{
int u,v,next;
}G[N<<1];
int head[N],inum;
inline void add(int u,int v,int p){
G[p].u=u; G[p].v=v; G[p].next=head[u]; head[u]=p;
}
int fat[N],size[N],depth[N];
int top[N],tid[N],clk;
#define V G[p].v
inline void dfs(int u,int fa){
fat[u]=fa; size[u]=1; depth[u]=depth[fa]+1;
for (int p=head[u];p;p=G[p].next)
if (V!=fa)
dfs(V,u),size[u]+=size[V];
}
inline void find(int u,int fa,int z){
int maximum=0,son=0; tid[u]=++clk; top[u]=z;
for (int p=head[u];p;p=G[p].next)
if (V!=fa && size[V]>maximum)
maximum=size[son=V];
if (son) find(son,u,z);
for (int p=head[u];p;p=G[p].next)
if (V!=fa && V!=son)
find(V,u,V);
}
inline void CC(int u,int v,int cc){
for (;top[u]!=top[v];u=fat[top[u]]){
if (depth[top[u]]<depth[top[v]]) swap(u,v);
Seg.Cover(tid[top[u]],tid[u],cc);
}
if (depth[u]>depth[v]) swap(u,v);
Seg.Cover(tid[u],tid[v],cc);
}
inline abcd SS(int u,int v){
data lret,rret,tmp;
abcd ret;
for (;top[u]!=top[v];){
if (depth[top[u]]>depth[top[v]]){
tmp=Seg.Sum(tid[top[u]],tid[u]); tmp.rev();
lret=lret+tmp; u=fat[top[u]];
}else{
tmp=Seg.Sum(tid[top[v]],tid[v]);
rret=tmp+rret; v=fat[top[v]];
}
}
if (depth[u]<depth[v]){
tmp=Seg.Sum(tid[u],tid[v]);
lret=lret+tmp;
}else{
tmp=Seg.Sum(tid[v],tid[u]); tmp.rev();
rret=tmp+rret;
}
lret=lret+rret;
return lret.ans;
}
int n;
int val[N][2];
int main(){
int Q,iu,iv,ic; char order[10]; abcd ret;
freopen("t.in","r",stdin);
freopen("t.out","w",stdout);
read(n);
for (int i=1;i<n;i++)
read(iu),read(iv),add(iu,iv,++inum),add(iv,iu,++inum);
dfs(1,0); find(1,0,1);
for (int i=1;i<=n;i++)
val[i][0]=val[i][1]=1;
Seg.Build(n);
read(Q);
while (Q--){
read(order);
if (!strcmp(order+1,"CVal")){
read(iu); read(iv); read(ic);
val[iu][iv]=ic;
Seg.CVal(tid[iu],val[iu][0],val[iu][1]);
}else if (!strcmp(order+1,"CColor")){
read(iu); read(iv); read(ic);
Seg.CColor(tid[iu],iv,ic,val[iu][0],val[iu][1]);
}else if (!strcmp(order+1,"Cover")){
read(iu); read(iv); read(ic);
CC(iu,iv,ic);
}else if (!strcmp(order+1,"QMax")){
read(iu); read(iv);
ret=SS(iu,iv);
if (ret.val>0)
printf("%lld\n",ret.val);
else
printf("Bad Request.\n");
}else if (!strcmp(order+1,"QLen")){
read(iu); read(iv);
ret=SS(iu,iv);
if (ret.val>0)
printf("%d\n",ret.len);
else
printf("0\n");
}
}
return 0;
}