题意:
给你一棵树,然后你有一个空的集合,能对集合进行两个操作
1.添加一个点到集合内
2.删除一个点从集合内
输出集合内的点按lca来连接出来的树形图的权值和
思路:
没思路…..QAQ
get一个公式就是在树上求点到链的公式
就x到链(u,v)
Dis=dis[x]-dis[lca(x,u)]-dis[lca(x,v)]+dis[lca(u,v)]
它确实是对的,但是我没有推出来怎么证明的….(如果有巨巨知道请告知一下…
添加点的时候就添加dfs序比x大的最小一个和比x小最大的一个,
如果某一个不存在就去集合内dfs序最大和最小的两个点的链到x的距离
话说这个set
#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
#include<math.h>
#include<queue>
#include<stack>
#include<string>
#include<vector>
#include<bitset>
#include<map>
#include<set>
using namespace std;
#define lowbit(x) (x&(-x))
typedef long long LL;
const int maxn = 100005;
const int inf=(1<<28)-1;
vector<pair<int,int> >vec[maxn];
map<int,int>Map;
int In[maxn],Out[maxn],tot,deep[maxn];
int ft[maxn][20],Pow[20],dis[maxn];
void dfs(int u,int fa,int dep)
{
In[u]=++tot;
Map[tot]=u;
deep[u]=dep;
for(int i=1;i<20;++i)
{
if(dep<Pow[i])
break;
ft[u][i]=ft[ft[u][i-1]][i-1];
}
int Size=vec[u].size();
for(int i=0;i<Size;++i)
{
int v=vec[u][i].first;
if(v!=fa)
{
ft[v][0]=u;
dis[v]=dis[u]+vec[u][i].second;
dfs(v,u,dep+1);
}
}
Out[u]=tot;
}
int lca(int u,int v)
{
if(deep[u]<deep[v])
swap(u,v);
int t=deep[u]-deep[v];
for(int i=0;i<20;++i)
if(t&Pow[i])
u=ft[u][i];
for(int i=19;i>=0;--i)
if(ft[u][i]!=ft[v][i])
{
u=ft[u][i];
v=ft[v][i];
}
if(u==v)
return u;
return ft[u][0];
}
set<int>Set1;
set<int>::iterator it1;
set<int,greater<int> >Set2;
set<int,greater<int> >::iterator it2;
int main()
{
Pow[0]=1;
for(int i=1;i<20;++i)
Pow[i]=Pow[i-1]*2;
int T,Case=0;
scanf("%d",&T);
while(T--)
{
printf("Case #%d:\n",++Case);
int n,q;
scanf("%d%d",&n,&q);
for(int i=1;i<=n;++i)
vec[i].clear();
for(int i=1;i<n;++i)
{
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
vec[u].push_back(make_pair(v,w));
vec[v].push_back(make_pair(u,w));
}
tot=0;
dis[1]=0;
Set1.clear();
Set2.clear();
Map.clear();
memset(ft,0,sizeof(ft));
dfs(1,-1,0);
LL Ans=0;
while(q--)
{
int chs,x;
scanf("%d%d",&chs,&x);
if(chs==1)
{
if(Set1.count(In[x]))
{
printf("%lld\n",Ans);
continue;
}
if(Set1.empty())
{
Set1.insert(In[x]);
Set2.insert(In[x]);
printf("0\n");
continue;
}
it1=Set1.upper_bound(In[x]);
it2=Set2.upper_bound(In[x]);
if(it1==Set1.end()||it2==Set2.end())
it1=Set1.begin(),it2=Set2.begin();
int u=Map[*it1],v=Map[*it2];
//printf("***%d %d\n",u,v);
Ans+=dis[x]-dis[lca(u,x)]-dis[lca(v,x)]+dis[lca(u,v)];
//printf("***%d %d %d\n",lca(u,x),lca(v,x),lca(u,v));
Set1.insert(In[x]);
Set2.insert(In[x]);
printf("%lld\n",Ans);
}
else
{
if(!Set1.count(In[x]))
{
printf("%lld\n",Ans);
continue;
}
Set1.erase(In[x]);
Set2.erase(In[x]);
if(Set1.empty())
{
printf("0\n");
continue;
}
it1=Set1.upper_bound(In[x]);
it2=Set2.upper_bound(In[x]);
if(it1==Set1.end()||it2==Set2.end())
it1=Set1.begin(),it2=Set2.begin();
int u=Map[*it1],v=Map[*it2];
//printf("***%d %d\n",u,v);
Ans-=dis[x]-dis[lca(u,x)]-dis[lca(v,x)]+dis[lca(u,v)];
printf("%lld\n",Ans);
}
}
}
return 0;
}