被两个zjoi搞得痛不欲生、、
这个题用线段树做的话,是:
利用树的dfs序,生成括号序列(化树为链),然后就可以利用区间结构维护了
匹配完之后一定都是“))((”的形式。这样区间ans就可以表达为:在左边的,在右边的,在两边的
所以就要做好衔接点的维护:
那么怎么判断那个点是黑点?
其实不用判断,只用考虑黑点与白点怎么合并就行了、
白点的所有要维护的值都为-INF,但C2、C5为0,这就是说括号可以传递,但最优值不能传递(这样最优值就不会选这个点的信息)
黑点所有要维护的值都为0,这样它就可以参与括号之间的转移,最优值的信息往上走也就会经历筛选。
但要注意:up十分难写,一个地方错了就炸了。
还要注意数组开的大小
而且,读入时要注意:ch!=\r !!\r!!!! \r !!!!一定是\r!!!!!
码:
#include<iostream>
#include<cstdio>
#include<vector>
using namespace std;
#define N 100005
#define zuo o<<1,l,mid
#define you o<<1|1,mid+1,r
#define INF 1e9
vector<int>v[N];
int bla,C2[N*12],hb[N],C5[N*12],M25[N*12],L2[N*12],R5[N*12],L25[N*12],R25[N*12],ch[N*3],dui[N*3],op,a,cnt,n,q,i,x,y,z;
char str;
void up(int now)
{
int l=now<<1;
int r=now<<1|1;
if(C2[r]>C5[l]) C2[now]=C2[l]+C2[r]-C5[l] ;else C2[now]=C2[l];
if(C2[r]>C5[l]) C5[now]=C5[r];else C5[now]=C5[r]+C5[l]-C2[r];
L2[now]=max(L2[l],L2[r]-C2[l]+C5[l]);
R5[now]=max(R5[r],R5[l]-C5[r]+C2[r]);
L25[now]=max(L25[l],max(C2[l]-C5[l]+L25[r],C2[l]+C5[l]+L2[r]));
R25[now]=max(R25[r],max(C5[r]-C2[r]+R25[l],C2[r]+C5[r]+R5[l]));
M25[now]=max(max(M25[l],M25[r]),max(R5[l]+L25[r],L2[r]+R25[l]));
}
void jian(int o,int l,int r)
{
if(l==r)
{
M25[o] = -INF;
if(ch[l]==-2){C2[o]=1;L25[o] = R25[o] = L2[o] = R5[o] =-INF;}
else if(ch[l]==-5){C5[o]=1;L25[o] = R25[o] = L2[o] = R5[o] =-INF;}
else
{
bla++;
L25[o] = R25[o] = L2[o] = R5[o] = 0;
}
return;
}
int mid=(l+r)>>1;
jian(zuo);
jian(you);
up(o);
}
void gai(int o,int l,int r)
{
if(l==r)
{
if(op==1)
{
L25[o] = R25[o] = L2[o] = R5[o] = -INF;
}else
{
L25[o] = R25[o] = L2[o] = R5[o] = 0;
}
return;
}
int mid=(l+r)>>1;
if(a<=mid)gai(zuo);
else gai(you);
up(o);
}
void dfs(int now,int fu)
{
ch[++cnt]=-5;
ch[++cnt]=now;
dui[now]=cnt;
for(int i=0;i<v[now].size();i++)
{
if(v[now][i]==fu)continue;
dfs(v[now][i],now);
}
ch[++cnt]=-2;
}
int main()
{
scanf("%d",&n);
for(i=1;i<n;i++)
{
scanf("%d%d",&x,&y);
v[x].push_back(y);
v[y].push_back(x);
}
dfs(1,0);
jian(1,1,cnt);
// for(i=1;i<=cnt;i++)
// if(ch[i]==-2)cout<<')';else if(ch[i]==-5)cout<<"(";else cout<<ch[i];
// cout<<endl;
scanf("%d",&q);
for(i=1;i<=q;i++)
{
scanf("%c",&str);
while(str=='\n'||str=='\0'||str=='\r')scanf("%c",&str);
if(str=='G')
{if(bla==0)printf("-1\n");
else if(bla==1)printf("0\n");
else printf("%d\n",M25[1]);
}else
{
scanf("%d",&z);
if(hb[z]==0)
{bla--;
hb[z]=1;
op=1;
a=dui[z];
gai(1,1,cnt);
}else
{bla++;
hb[z]=0;
op=0;
a=dui[z];
gai(1,1,cnt);
}
}
}
}