최근 코드의 가장 큰 금액에 제목을 수행 (물론, 내가 못생긴 쓰기 ....)
문제의 의미
\ (N- \) 트리 노드 ( \ (N- \ 르. 5 ^ 10 \) ) 각 노드는 검은 색 또는 흰색입니다.
거기 \ (m \) 동작 ( \ (m \ 르. 5 \ 10 ^ 5 번 \) ), 두 개의 동작이 있으며,
- 점 \ (X \) 색상 반전.
- 오른쪽 멀리 나무 검은 점 사이의 거리를 쿼리합니다.
사고
첫째, 수정 작업없이, 다음, 베어 점선 규칙입니다 ( 점선 규칙 연구 노트 ).
작동, 다음이 수정 분할과 정복의 동적 점을 .
나무가 먼저 무게 중심을 찾을 수 있도록, 변경, 빌드하지 않으므로 : 기본적인 아이디어는 동적 포인트 (개인 요약)를 분할하는 것입니다 점선 트리 (각 층의 무게 중심을 연결하는 나무), 분할 및 정복의 다음 유지 보수 지점을 필요가 시간 재귀 발견을 폐기물로 인한 무게 중심을 피하고, 데이터를 알고 있습니다.
기본적인 아이디어는 간단하다, 데이터를 요약하기 어려운 그들은 유지하기 위해 알 필요가있다.
(참고 : 아래에 달리 지정되지 않을 경우, "아들", "하위 트리", "아버지", "거리"등의 용어는 원래 나무 참조)
이 질문에, 우리는 파티션 프로세스의 지점에있다, 알고 각 지점의 요구에 대한 데이터는 다음과 같습니다
그것은하는 중력의 중심에있을 때 , 노드 관할 블랙 그 행 의 최대 값으로부터의 거리와 두 번째로 큰 값은 , 데이터 1이라고.
그 중심에있을 때, 그것을 관할하는 모든 점 층의 중심 (즉,이 트리 아버지 포인트 포인트 ) 데이터 (2)로 지칭 거리.
이들 두 데이터 사이의 관계가있다 :
자신의 지점 이 데이터를 최대 에 기여하는 점 나무 아버지 , 점선 나무 아버지의 각 아들에 따라 최대 기여는 자신에게주는 최대 값과 두 번째로 큰 값 데이터 1 .
분명히, 최대 값과 두 번째로 큰 값을 얻을 수있는 과정에서, 우리는 데이터 구조를 지원하는 일종의 필요, 여기에 우리가 사용하도록 선택할 힙 .
우리는 방금 언급 한 점으로 나무를 좀 더 분명 성격이 : 그 나무의 높이 입니다 \ (N 로그 \ \) 수준.
다음 우리는 조상 각각의 데이터만을 유지하기 위해, 노드 수정 때 () O (\ 로그 n \를 \) 시간 복잡도.
힙 자체가 삭제 작업을 지원하지 않는 동안 그러나, 유지 보수 과정에서, 우리는 삭제 작업을 사용해야합니다.
우리는 약간의 트릭을 사용할 수 있습니다 : 힙을 넣어 두 부분으로 , 하나는 인 정렬 힙 , 하나는 힙을 삭제합니다 .
우리가 값을 삭제해야하는 경우, 값이 단지 필요가 삭제 힙에 가입 ,
정렬 힙 및 스택 삭제하면 최대 값이 때 힙 요소의 동일한 상단을 ,이 요소는, 그들은 둘 다 팝업 제거 된 것을 의미한다.
따라서, 우리는 시간 복잡도를 얻을 \ (O (n \ 로그 ^ 2 N) \) 알고리즘, 스택 (우선 순위 큐)의 사용, 상수는 비교적 클 것이다.
로스 밸리 의지의 코드의 저자 \ (TLE \) 를 통해 bzoj의 점. 그리고 코드는 상대적으로 추한 코드를보고하지 않는 것이 좋습니다 이해합니다. 정말 루오 구 코드에 대한 첫 번째, 당신이 볼 수있는 문제에 대한 해결책을보고 싶어요.
코드
#include<bits/stdc++.h>
using namespace std;
const int _=1e5+7;
const int __=2e5+7;
const int L=20;
const int inf=0x3f3f3f3f;
struct hep{
priority_queue<int> A,B;
void push(int x){ A.push(x); }
void del(int x){ B.push(x); }
int top(){
while(!A.empty()&&!B.empty()&&A.top()==B.top()){ A.pop(); B.pop(); }
return A.empty() ?-1 :A.top();
}
int sec(){
int x=top();
if(x==-1) return x;
A.pop();
int y=top();
A.push(x);
return y;
}
}h1[_],h2[_],ans;
int n,m,dep[_],f[_][L+7],dis[_],sz[_],rt,minx=inf,ft[_],lt[_];
int lst[_],nxt[__],to[__],tot;
bool vis[_],sta[_];
int gi(){
char c=getchar(); int x=0,f=1;
while(c<'0'||c>'9'){ f=c=='-'?-1:1; c=getchar(); }
while(c>='0'&&c<='9'){ x=(x<<3)+(x<<1)+c-'0'; c=getchar(); }
return x*f;
}
void add(int x,int y){ nxt[++tot]=lst[x]; to[tot]=y; lst[x]=tot; }
int Lca(int x,int y){
if(dep[x]<dep[y]) swap(x,y);
for(int i=L;i>=0;i--)
if(dep[f[x][i]]>=dep[y])
x=f[x][i];
if(x==y) return x;
for(int i=L;i>=0;i--)
if(f[x][i]!=f[y][i]){
x=f[x][i];
y=f[y][i];
}
return f[x][0];
}
int dist(int x,int y){ return dep[x]+dep[y]-2*dep[Lca(x,y)]; }
void idk(int u,int fa){
dep[u]=dep[fa]+1;
f[u][0]=fa;
for(int i=1;i<=L;i++)
f[u][i]=f[f[u][i-1]][i-1];
for(int i=lst[u];i;i=nxt[i]){
int v=to[i];
if(v==fa) continue;
idk(v,u);
}
}
void pre(int u,int fa,bool id){
if(id) h1[rt].push(dis[u]+1);
sz[u]=1; dis[u]=dis[fa]+1;
for(int i=lst[u];i;i=nxt[i]){
int v=to[i];
if(v==fa||vis[v]) continue;
pre(v,u,id);
sz[u]+=sz[v];
}
}
void g_rt(int u,int fa,int sum){
int maxn=sum-sz[u];
for(int i=lst[u];i;i=nxt[i]){
int v=to[i];
if(v==fa||vis[v]) continue;
g_rt(v,u,sum);
maxn=max(maxn,sz[v]);
}
if(maxn<minx){ minx=maxn; rt=u; }
}
void upd(int u,int id){
int t1=h2[u].top(),t2=h2[u].sec();
if(id){
if(t1==-1);
else if(t2==-1) ans.push(0);
else ans.push(t1+t2);
}
else{
if(t1==-1);
else if(t2==-1) ans.del(0);
else ans.del(t1+t2);
}
}
void init(int u,int lrt){
minx=inf;
pre(u,0,0);
g_rt(u,0,sz[u]);
//printf("u: %d rt: %d dis[rt]: %d\n",u,rt,dis[rt]);
dis[rt]= lrt ?dis[rt] :-1;
ft[rt]=lrt;
lt[rt]=dis[rt]+1; // 因为此时的 dis 是到 lrt 的子节点的距离, 所以要加上 1
pre(rt,0,1);
h2[lrt].push(h1[rt].top());
vis[rt]=1; u=rt;
for(int i=lst[u];i;i=nxt[i]){
int v=to[i];
if(vis[v]) continue;
init(v,u);
}
vis[u]=0;
h2[u].push(0);
upd(u,1);
}
void modify(int u){
sta[u]^=1;
int len=lt[u],fa=ft[u],t=u;
upd(u,0);
//printf("%d %d\n",h2[u].top(),h2[u].sec());
if(sta[u]){ h2[u].del(0); }
else h2[u].push(0);
upd(u,1);
while(fa){
int top=h1[u].top(),sec=h2[fa].sec();
bool f1= len>=top,f2= len>=sec;
if(f1){
if(f2) upd(fa,0);
h2[fa].del(top);
if(sta[t]){ h1[u].del(len); h2[fa].push(h1[u].top()); }
else{ h1[u].push(len); h2[fa].push(len); }
if(f2) upd(fa,1);
}
else{
if(sta[t]) h1[u].del(len);
else h1[u].push(len);
}
u=ft[u]; fa=ft[u];
len=dist(t,fa);
}
}
char ss[_];
void run(){
m=gi(); char c; int x;
for(int i=1;i<=m;i++){
//gets(ss);
c=getchar();
//printf("%s %c\n",ss,c);
if(c=='G') printf("%d\n",ans.top());
else{
x=gi();
//printf("x: %d\n",x);
modify(x);
//puts("!!!");
}
}
}
int main(){
//freopen("x.in","r",stdin);
//freopen("x.out","w",stdout);
n=gi(); int x,y;
for(int i=1;i<n;i++){
x=gi(); y=gi();
//printf("%d %d\n",x,y);
add(x,y);
add(y,x);
}
dis[0]=-1;
idk(1,0);
init(1,0);
run();
return 0;
}