记录编号 |
223826 |
评测结果 |
AAAAAAAAAA |
题目名称 |
[SPOJ 2666] QTREE4 |
最终得分 |
100 |
用户昵称 |
mikumikumi |
是否通过 |
通过 |
代码语言 |
C++ |
运行时间 |
2.906 s |
提交时间 |
2016-02-13 17:42:27 |
内存使用 |
85.16 MiB |
显示代码纯文本
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<set>
#include<queue>
using namespace std;
const int SIZEN=410000;
int N;
bool co[SIZEN]={0};//0代表白,1代表黑
class point
{
public:
int dist,x;
bool operator < (const point &b) const
{
return dist<b.dist;
}
};
class miku
{
public:
int fr,to,lo;
bool type;
miku(){}
miku(int a,int b,int c)
{
fr=a,to=b,lo=c;
type=1;
}
}e[SIZEN],E[SIZEN];//
class poi//用来储存分治中每棵子树的信息
{
public:
int st;
priority_queue<point> Q;
int lc,rc;
int midlen;
int ans;
void print()
{
cout<<"st:"<<st<<endl;
cout<<lc<<" "<<rc<<endl;
cout<<"midlen:"<<midlen<<endl;
cout<<ans<<endl;
}
}tr[SIZEN*4];
vector<int> s[SIZEN];//第一次建图时使用
vector<int> S[SIZEN];//第二次建图时使用
vector<pair<int,int> > c[SIZEN];
int tot=0;
int n;
int cnt;
int siz[SIZEN];
void add(int fr,int to,int lo)
{
s[fr].push_back(tot);e[tot++]=miku(fr,to,lo);
s[to].push_back(tot);e[tot++]=miku(to,fr,lo);
}
void ADD(int fr,int to,int lo)
{
S[fr].push_back(tot);E[tot++]=miku(fr,to,lo);
S[to].push_back(tot);E[tot++]=miku(to,fr,lo);
}
void read()
{
scanf("%d",&N);
int v,u,lo;
for(int i=1;i<N;i++)
{
scanf("%d%d%d",&v,&u,&lo);
add(v,u,lo);
}
}
void check(int x,int fa)
{
int father=0;
for(int i=0;i<s[x].size();i++)
{
int v=e[s[x][i]].to,w=e[s[x][i]].lo;
if(v==fa) continue;
if(father==0)
{
ADD(x,v,w);
father=x;
check(v,x);
}
else
{
++n;co[n]=1;
ADD(father,n,0);ADD(n,v,w);
father=n;
check(v,x);
}
}
}
void rebuilt()//添加虚点
{
n=N;
check(1,0);
}
void ADD1(int x,int y,int dist)
{
c[x].push_back(make_pair(y,dist));
}
void getsize(int beg,int u,int fa,int dist)
{
ADD1(u,beg,dist);if(!co[u]) tr[beg].Q.push((point){dist,u});
siz[u]=1;
for(int i=0;i<S[u].size();i++)
{
int v=E[S[u][i]].to,w=E[S[u][i]].lo;
int ok=E[S[u][i]].type;
if(v==fa||ok==0) continue;
getsize(beg,v,u,dist+w);
siz[u]+=siz[v];
}
}
int midedge,mi;
void getmid(int beg,int u,int code)//寻找中心边
{
if(max(siz[u],siz[tr[beg].st]-siz[u])<mi)
{
mi=max(siz[u],siz[tr[beg].st]-siz[u]);
midedge=code;
}
for(int i=0;i<S[u].size();i++)
{
int tmp=S[u][i];
int p=E[tmp].type;
if(tmp==(code^1)||p==0) continue;
getmid(beg,E[tmp].to,tmp);
}
}
void push(int pt)
{
tr[pt].ans=-1;
while(!tr[pt].Q.empty()&&co[tr[pt].Q.top().x]==1) tr[pt].Q.pop();
int lc=tr[pt].lc,rc=tr[pt].rc;
if(tr[pt].lc==0&&tr[pt].rc==0)
{
if(!co[tr[pt].st]) tr[pt].ans=0;
}
else
{
if(tr[lc].ans>tr[pt].ans) tr[pt].ans=tr[lc].ans;
if(tr[rc].ans>tr[pt].ans) tr[pt].ans=tr[rc].ans;
if(!tr[lc].Q.empty()&&!tr[rc].Q.empty())
{
tr[pt].ans=max(tr[pt].ans,tr[lc].Q.top().dist+tr[rc].Q.top().dist+tr[pt].midlen);
}
}
}
void dfs(int pt,int u)
{
tr[pt].st=u;
getsize(pt,u,0,0);
midedge=-1;mi=n;getmid(pt,u,-1);
//cout<<pt<<" "<<midedge<<endl;
if(midedge!=-1)
{
miku tmp=E[midedge];
tr[pt].midlen=tmp.lo;
E[midedge].type=0;
E[midedge^1].type=0;
dfs(tr[pt].lc=++cnt,tmp.fr);
dfs(tr[pt].rc=++cnt,tmp.to);
}
push(pt);
}
void change(int x)
{
co[x]^=1;
if(co[x]==1)
for(int i=c[x].size()-1;i>=0;i--)
{
push(c[x][i].first);
}
else
{
for(int i=c[x].size()-1;i>=0;i--)
{
tr[c[x][i].first].Q.push((point){c[x][i].second,x});
push(c[x][i].first);
}
}
}
void work()
{
int Q;
scanf("%d",&Q);
int x;
char a[10];
for(int i=1;i<=Q;i++)
{
//cout<<i<<endl;
scanf("%s",a);
if(a[0]=='A')
{
if(tr[1].ans==-1) printf("They have disappeared.\n");
else printf("%d\n",tr[1].ans);
}
else
{
scanf("%d",&x);
change(x);
}
}
}
int main()
{
freopen("QTREE4.in","r",stdin);
freopen("QTREE4.out","w",stdout);
read();
tot=0;
rebuilt();
dfs(cnt=1,1);
work();
return 0;
}