1554:【例 3】异象石

1554:【例 3】异象石


时间限制: 1000 ms         内存限制: 524288 KB
提交数: 627     通过数: 285

【题目描述】

原题来自:Contest Hunter Round #56

在 Adera 的异时空中有一张地图。这张地图上有 NN 个点,有 N1N−1 条双向边把它们连通起来。起初地图上没有任何异象石,在接下来的 MM 个时刻中,每个时刻会发生以下三种类型的事件之一:

地图的某个点上出现了异象石(已经出现的不会再次出现);

地图某个点上的异象石被摧毁(不会摧毁没有异象石的点);

向玩家询问使所有异象石所在的点连通的边集的总长度最小是多少。

请你作为玩家回答这些问题。下图是一个例子,灰色节点表示出现了异象石,加粗的边表示被选为连通异象石的边集。

【输入】

第一行有一个整数 NN,表示点的个数;

接下来 N1N−1 行每行三个整数 x,y,zx,y,z,表示点 xx 和 yy 之间有一条长度为 zz 的双向边;

第 N+1N+1 行有一个正整数 MM;

接下来 MM 行每行是一个事件,事件是以下三种格式之一:

+x+x:表示点 xx 上出现了异象石;

x−x:表示点 xx 上的异象石被摧毁;

??:表示询问使当前所有异象石所在的点连通所需的边集的总长度最小是多少。

【输出】

对于每个 ?? 事件,输出一个整数表示答案。

【输入样例】

6 
1 2 1 
1 3 5 
4 1 7 
4 5 3 
6 4 2 
10 
+ 3 
+ 1 
? 
+ 6 
? 
+ 5 
? 
- 6 
- 3 
?

【输出样例】

5 
14 
17 
10

【提示】

数据范围与提示:

对于 30% 的数据,1n,m1031≤ n,m ≤ 103 ;

对于另 20% 的数据,地图是一条链,或者一朵菊花;

对于 100% 的数据,1n,m105,1x,yn,xy,1z1091≤ n,m ≤ 105,1 ≤ x,y ≤ n,x≠ y,1 ≤ z ≤ 109 。

【代码】

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<queue>
#include<set>
#include<ctime>
#define maxn 100005
#define maxx 18
#define ll long long
using namespace std;
int head[maxn],_next[maxn<<1],to[maxn<<1],w[maxn<<1];
int edge;
void addEdge(int x,int y,int z)
{
    to[++edge]=y,w[edge]=z,_next[edge]=head[x],head[x]=edge;
    to[++edge]=x,w[edge]=z,_next[edge]=head[y],head[y]=edge;
}
int d[maxn];
ll dis[maxn];
queue<int>que;
int n,m,N;
int f[maxn][maxx];
void bfs()
{
    d[1]=1;
    que.push(1);
    while(que.size())
    {
        int u=que.front();que.pop();
        for(int i=head[u];i;i=_next[i])
        {
            int v=to[i];
            if(d[v])continue;
            d[v]=d[u]+1;
            dis[v]=dis[u]+w[i];
            f[v][0]=u;
            for(int i=1;i<=N;i++)
                f[v][i]=f[f[v][i-1]][i-1];
            que.push(v);
        }
    }
}
int lca(int a,int b)
{
    if(d[a]>d[b])swap(a,b);
    for(int i=N;i>=0;i--)
        if(d[a]<=d[f[b][i]])b=f[b][i];
    if(a==b)return a;
    for(int i=N;i>=0;i--)
        if(f[a][i]!=f[b][i])a=f[a][i],b=f[b][i];
    return f[a][0];
}
ll getRoad(int a,int b)
{
    return dis[a]+dis[b]-2*dis[lca(a,b)];
}
int dfn[maxn],ind;
void dfs(int u,int fa)
{
    dfn[u]=++ind;
    for(int i=head[u];i;i=_next[i])
    {
        int v=to[i];
        if(v==fa)continue;
        dfs(v,u);
    }
}

void init()
{
    //memset(head,0,sizeof(head));
    edge=0;
    N=(int)log2(n)+1;
}
struct cmp
{
    bool operator() (const int&a,const int&b)
    {
        return dfn[a]<dfn[b];
    }
};
set<int,cmp>_set;
int main()
{
    //cout<<log2(maxn)<<endl;
    cin>>n;
    init();
    int x,y,z;
    for(int i=1;i<n;i++)
    {
        scanf("%d%d%d",&x,&y,&z);
        addEdge(x,y,z);
    }
    //clock_t start,finish;
    //start=clock();
    bfs();
    dfs(1,0);
    char s[5];
    cin>>m;
    ll ans=0;
    set<int,cmp>::iterator it,_it;
    while(m--)
    {
        scanf("%s",s);
        if(s[0]=='?')
            printf("%lld\n",ans/2);
        else
        {
            scanf("%d",&x);
            if(s[0]=='+')
            {
                _set.insert(x);
                if(_set.size()>1)
                {
                    it=_set.find(x);
                    _it=_set.end();
                    _it--;
                    int l,r;
                    if(it==_set.begin())l=*(_it);
                    else
                    {
                        it--;l=*it;it++;
                    }
                    it++;
                    if(it==_set.end())r=*(_set.begin());
                    else r=*it;
                    ans-=getRoad(l,r);ans+=getRoad(l,x);ans+=getRoad(x,r);
                }
            }
            else
            {
                if(_set.size()>1)
                {
                    it=_set.find(x);
                    _it=_set.end();
                    _it--;
                    int l,r;
                    if(it==_set.begin())l=*(_it);
                    else
                    {
                        it--;l=*it;it++;
                    }
                    it++;
                    if(it==_set.end())r=*(_set.begin());
                    else r=*it;
                    ans+=getRoad(l,r);ans-=getRoad(l,x);ans-=getRoad(x,r);
                }
                _set.erase(x);
            }
        }
    }
    //finish=clock();
    //printf("%.3lf\n",(finish-start)/CLOCKS_PER_SEC);
    return 0;
}
posted @ 2022-05-12 12:01  刘炳源  阅读(148)  评论(0)    收藏  举报