BZOJ1912 Alien Stone (LCA / DFS Order / set)

Adera is a puzzle game in the Microsoft App Store.

The vision stone is a guide to enter the space and time in Adera. There is a map in the space and time in Adera.

There are N points on this map, and there are N-1 bidirectional edges connecting them.

At first there were no vision stones on the map. In the next M moments, one of the following three types of events will occur at each moment:

  1. A vision stone appears at a point on the map (when it already appears, it will not appear again);
  2. The vision stone at a certain point on the map is destroyed (it will not destroy the point without the vision stone);
  3. Ask the player what is the minimum total length of the edge set that connects the points where all vision stones are located.

Please answer these questions as a player.

Input format

The first line has an integer N, which represents the number of points.

The next three integers x, y, z in each line of line N-1 indicate that there is a bidirectional edge of length z between points x and y.

Line N + 1 has a positive integer M.

Each line in the next M lines is an event. The event is in one of the following three formats:

”+ X” indicates that a vision stone appeared at point x

"-X" means that the vision stone at point x is destroyed

"?" Means asking what is the minimum total length of the edge set required to connect all the current vision points.

Output format

For each? Event, output an integer representing the answer.

data range

1N,M1051≤N,M≤105,
1x,yN1≤x,y≤N,
xyx≠y,
1z1091≤z≤109

Sample input:

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

Sample output:

5
14
17
10
蓝书上的例题,主要说一下注意的地方。
1.dist数组和ans都要开long long,不然见祖宗。
2.既然要求时间戳,不如直接dfs预处理f数组(不要按照蓝书板子用bfs求了)。
3.注意,set里面的s.end()返回的是指向最后一个元素下一个位置的迭代器!这个位置存放的是set的size!同时迭代器只能自增自减,要么写函数处理要么多设置几个迭代器。
4.注意下魔鬼输入。看到有博客这么写觉得很巧妙:
char c = getchar();
while (c != '+' && c != '-' && c != '?') c = getchar();
#include <bits/stdc++.h>
#define N 100005
using namespace std;
int t,n,m,tot=0,head[N],edge[N*2],Next[N*2],ver[N*2],f[N][25],d[N];
long long dist[N];
int cnt=0;//时间戳 
long long ans=0;
struct node
{
    int x;
    int t;//时间戳 
}nod[N];
struct cmp 
{
    bool operator () ( const node & a, const node & b) const {
         return at < bt; 
    } 
}; 
set <node, cmp> s;
 void add ( int x, int y, int z) 
{ 
    ver [ ++ tot] = y, edge [tot] = z, Next [tot] = head [x], head [x] = tot; 
} 
void dfs ( int x, int pre) // Because you want to record the timestamp, use dfs 
{
     int i ; 
    nod [x] .t = (++ cnt);
     for(i=head[x];i;i=Next[i])
    {
        int y=ver[i],z=edge[i];
        if(y==pre)continue;
        d[y]=d[x]+1;
        dist[y]=dist[x]+(long long)z;
        f[y][0]=x;
        int j;
        for(j=1;j<=t;j++)f[y][j]=f[f[y][j-1]][j-1];
        dfs(y,x);
    }
 } 
int lca(int x,int y)
{
    if(d[x]>d[y])swap(x,y);
    int i;
    for(i=t;i>=0;i--)
    {
        if(d[f[y][i]]>=d[x])y=f[y][i];
    }
    if(x==y)return x;
    for(i=t;i>=0;i--)
        if(f[y][i]!=f[x][i])x=f[x][i],y=f[y][i];
    return f[x][0];
}
long long path(int x,int y)
{
    int anc=lca(x,y);
    return dist[x]+dist[y]-2*dist[anc];
 } 
int main()
{
    int i;
    cin>>n;
    for(i=1;i<=n;i++)nod[i].x=i;
    d[1]=1,dist[1]=0;
    t=(int)(log(n)/log(2))+1;
    for(i=1;i<=n-1;i++)
    {
        int x,y,z;
        scanf("%d%d%d",&x,&y,&z);
        add(x,y,z);
        add(y,x,z);
    }
    dfs(1,0);
    scanf("%d",&m);
    for(i=1;i<=m;i++)
    {
        char c = getchar();
        while (c != '+' && c != '-' && c != '?') c = getchar();
        int x,l,r;
        set<node,cmp> :: iterator it1,it2;
        if(c==' + ' ) 
        { 
            scanf ( " % d " , & x); 
            s.insert (nod [x]); 
            it1 = it2 = s.find (nod [x]);
             if (it1 == s.begin () ) l = (-s.end ())-> x; // ? Make sure to
             connect end to end else l = (-it1)-> x;     // Only increase and decrease         
            if (++ it2 == s.end ()) r = (s.begin ())-> x; // ? 
            else r = (it2)-> x; 
            ans + = path (l, x) + path (x, r) -path (l, r);
             // cout << l << '' << r << endl;

        }
        else if(c == ' - ' ) 
        { 
            scanf ( " % d " , & x); 
            it1 = it2 = s.find (nod [x]);
             set <node, cmp> :: iterator temp = it1; // From After increasing and decreasing, the position of x can be found to delete 
            if (it1 == s.begin ()) l = (-s.end ())-> x; // ? 
            Else l = (-it1) -> x;
             if (++ it2 == s.end ()) r = (s.begin ())-> x; // ? 
            else r = (it2)-> x; 
            ans + = path (l, r) -path (l, x)-path ( x, r); 
            s.erase (temp); //Do n’t forget to delete 
        }
         else 
        { 
            cout << ans / 2 << endl; 
        } 
    } 
// 9
 // 1 2 1
 // 1 3 5
 // 1 4 2
 // 2 5 4
 // 2 6 4
 // 4 7 7
 // 4 8 5
 // 7 9 3 
}

 

 

Guess you like

Origin www.cnblogs.com/lipoicyclic/p/12674872.html
lca