比赛的时候以为这是一道动态维护树的中心,看了题解发现自己想错了,公共祖先的题目确实是少
这次学习了一下set
发现有很多使用简便的地方
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <set>
#include <utility>
using namespace std;
#define N 111111
#define iter set<int>::iterator
int par[N][20];
int depth[N];
int dis[N];
int n,m;
int p[N];
int vis[N];
int cnt;
int dfn[N];
vector<pair<int,int>>edge[N];
set<int> ans;
void dfs(int u,int fa){
dfn[++cnt]=u;
p[u]=cnt;
//printf("%d %d\n",u,fa);
for(int i=1;i<18;i++){ //寻找他的十八辈祖宗
par[u][i]=par[par[u][i-1]][i-1];
}
for(int i=0;i<edge[u].size();i++){
int v=edge[u][i].first;
if(fa==v) continue ;
depth[v] = depth[u] + 1;
dis[v] = dis[u] + edge[u][i].second;
par[v][0] = u;
dfs(v,u);
}
}
int lca(int u,int v){
if(depth[u]>depth[v]) swap(u,v);
for(int k=0;k<18;k++){
if((depth[v]-depth[u])>>k&1){
v = par[v][k];
}
}
if(v==u) return u;
for(int k=17;k>=0;k--){
if(par[u][k]!=par[v][k]){
u=par[u][k];
v=par[v][k];
}
}
return par[u][0];
}
int tot;
int add(int u){
if (ans.empty())
return 0;
int x, y;
//寻找与u相邻的dfs序点
iter it = ans.lower_bound(p[u]);
iter itx = it;
itx--;
if (it == ans.end() || it == ans.begin()) {
it = ans.begin();
itx = ans.end();
itx--;
}
y = (*it);
x = (*itx);
y = dfn[y];
x = dfn[x];
return dis[u] - dis[lca(x, u)] - dis[lca(y, u)] + dis[lca(x, y)];
}
void init(){
for(int i=1;i<=n;i++){
edge[i].clear();
}
memset(vis,0,sizeof(vis));
memset(dfn,0,sizeof(dfn));
memset(p,0,sizeof(p));
memset(par,0,sizeof(par));
memset(dis,0,sizeof(dis));
memset(depth,0,sizeof(depth));
cnt=0;
ans.clear();
}
int main(){
int T;
int cas = 0;
scanf("%d",&T);
while(T--){
scanf("%d%d",&n,&m);
init();
int x,y,z;
for(int i=1;i<n;i++){
scanf("%d%d%d",&x,&y,&z);
edge[x].push_back(make_pair(y,z));
edge[y].push_back(make_pair(x,z));
}
/*
for(int i=1;i<=n;i++){
printf("%d :",i);
for(int j=0;j<edge[i].size();j++){
printf("%d ",edge[i][j].first);
}
puts("");
}
*/
dis[1]=0;
depth[1]=1;
dfs(1,-1);
/*
for(int i=1;i<=n;i++){
printf("%d %d %d\n",i,dis[i],par[i][0]);
}
*/
int sum=0;
printf("Case #%d:\n",++cas);
for(int i=1;i<=m;i++){
scanf("%d%d",&x,&y);
int tmp;
if(x==1){
if(!vis[y]){
vis[y]=1;
if (ans.size() == 0) {
ans.insert(p[y]);
} else {
tmp = add(y);
ans.insert(p[y]);
sum += tmp;
}
}
}
else{
if(vis[y]){
vis[y] = 0;
ans.erase(p[y]);
if (!ans.empty()) {
sum -= add(y);
}
}
}
printf("%d\n",sum);
}
}
}
版权声明:都是兄弟,请随意转载,请注明兄弟是谁
原文地址:http://blog.csdn.net/u013076044/article/details/47004313