洛谷3320 SDOI2015尋寶遊戲(set+dfs序)(反向迭代器的注意事項!)
阿新 • • 發佈:2018-12-04
被 坑害了一個晚上,真的菜的沒救了啊。
準確的說是一個叫 的東西,就是我們經常用的
有一個非常重要的性質
在反向迭代器中,++相當於正常的–,--相當於正常的++
也就是說
假設我們要訪問
中的倒數第二個元素,我們要
而不是一些別的東西
好
我們回到這個題,對於這個題目來說,其實我的第一反應是虛樹,QWQ但事實證明,並不能用虛樹來解決這個問題。
我們可以通過一些方式,發現,無論從哪個有寶藏的點出發,訪問所有點的總距離都是一定的。那麼我們可以強制按照 順序,每個點從 的上一個節點走過來,然後走向 的下一個節點,那麼刪除的之後,我們要是知道每個點的前驅和後繼的話,就可以考慮直接更新 了,(但是要特判第一個點和最後一個點,第一個點的前驅是最後一個點,最後一個點的後繼是第一個點)
那麼既然需要一個排序+前驅後繼的資料結構,自然就是 了
不過需要注意的是。
的問題!!!!!!!!!!!!!!
直接給程式碼了
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<map>
#include<set>
#define mk makr_pair
#define ll long long
#define int long long
using namespace std;
inline int read()
{
int x=0,f=1;char ch=getchar();
while (!isdigit(ch)) {if (ch=='-') f=-1;ch=getchar();}
while (isdigit(ch)) {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
return x*f;
}
const int maxn = 2e5+1e2;
const int maxm = 2*maxn;
const int inf = 1e9;
int point[maxn],nxt[maxm],to[maxm];
int cnt,n,m;
int dfn[maxn],deep[maxn],f[maxn][21];
set<int> s;
int tot;
int dis[maxn];
int mp[maxn];
int ans;
int val[maxm],tag[maxn];
void addedge(int x,int y,int w)
{
nxt[++cnt]=point[x];
to[cnt]=y;
val[cnt]=w;
point[x]=cnt;
}
void dfs(int x,int fa,int dep)
{
deep[x]=dep;
dfn[x]=++tot;
mp[tot]=x;
for (int i=point[x];i;i=nxt[i])
{
int p = to[i];
if (p==fa) continue;
f[p][0]=x;
dis[p]=dis[x]+val[i];
dfs(p,x,dep+1);
}
}
void init()
{
for (int j=1;j<=20;j++)
for (int i=1;i<=n;i++)
f[i][j]=f[f[i][j-1]][j-1];
}
int go_up(int x,int d)
{
for (int i=0;i<=20;i++)
if ((1<<i) & d) x=f[x][i];
return x;
}
int lca(int x,int y)
{
if (deep[x]>deep[y]) x=go_up(x,deep[x]-deep[y]);
else y=go_up(y,deep[y]-deep[x]);
if (x==y) return x;
for (int i=20;i>=0;i--)
{
if (f[x][i]!=f[y][i])
{
x=f[x][i];
y=f[y][i];
}
}
return f[x][0];
}
int getdis(int x,int y)
{
return dis[x]-2*dis[lca(x,y)]+dis[y];
}
int getpre(int x)
{
set<int> :: iterator it = s.lower_bound(x);
--it;
if ((*it)==-inf) return mp[*(++s.rbegin())];
else return mp[(*it)];
}
int getlas(int x)
{
set<int> :: iterator it = s.upper_bound(x);
if ((*it)==inf) return mp[*(++s.begin())];
else return mp[(*it)];
}
signed main()
{
//freopen("game.in.txt","r",stdin);
//freopen("game.out","w",stdout);
n=read();m=read();
for (int i=1;i<n;i++)
{
int x=read(),y=read(),w=read();
addedge(x,y,w);
addedge(y,x,w);
}
dfs(1,0,1);
init();
s.insert(inf);
s.insert(-inf);
for (int i=1;i<=m;i++)
{
int x=read();
if (tag[x])
{
int pre = getpre(dfn[x]);
int last = getlas(dfn[x]);
// cout<<"you:"<<pre<<" "<<last<<endl;
ans=ans-getdis(pre,x)-getdis(last,x);
ans=ans+getdis(pre,last);
s.erase(dfn[x]);
tag[x]=0;
}
else
{
if (s.size()==2)
{
s.insert(dfn[x]);
tag[x]=1;
cout<<ans<<"\n";
continue;
}
int pre = getpre(dfn[x]);
//cout<<1<<endl;
int last = getlas(dfn[x]);
// cout<<"meiyou:"<<pre<<" "<<last<<" "<<getdis(pre,x)<<" "<<lca(pre,x)<<" "<<dis[pre]<<" "<<dis[x]<<endl;
ans=ans-getdis(pre,last);
ans=ans+getdis(pre,x)+getdis(last,x);
s.insert(dfn[x]);
tag[x]=1;
}
cout<<ans<<"\n";
}
return 0;
}