Vision Stone / [SDOI2015] treasure hunt

AcWing vision stone

Los cushions treasure hunt

Meaning of the questions: Adera is a Microsoft application store in a puzzle game.

Stone is a different time and space into the vision of Adera guide was there a map of Adera in different time and space.

There are on this map \ (N (N <= 1e5 ) \) points with a \ (N-1 \) bidirectional communication edges them together.

At first no vision stone on the map, the next \ (M (M <= 1e5 ) \) time, each time one of the following three types of events occur:

Stone appeared in a vision of a point on the map (not already occur again);

Vision Stone on the map some point be destroyed (not destroy no vision stone points);

Asks the player to make the vision of all the stone where the total length of the edge set point is communicated minimum number?

Analysis: The map is actually a tree, we Fengyun tree \ (dfs \) , calculated for each node time stamp, that is, \ (dfs \) sequence then appears node vision stone in accordance with a time stamp. in ascending order (end to end), the accumulated path length between two adjacent nodes, the answer exactly twice the required answers.

So we just need to create a \ (the SET \) , the point appears vision stone thrown into it (according to the time stamp from small to large) enough. Every time there is a new vision stone \ (the X-\) , it is \ (INSERT \) operation while updating \ (ANS ANS = + dist (pre, X) + dist (X, NXT) -dist (pre, NXT) \) . each time the destruction of a stone vision, that is, \ (ERASE \) operation while updating answer \ (ANS ANS-dist = (pre, X) -dist (X, NXT) + dist (pre, NXT) \) . asks the operator for direct output \ (ans / 2 \) to .

For any two trees \ (X, Y \) , \ (dist (X, Y) = D [X] + D [Y] -2 * D [the LCA (X, Y)]. \) Where \ ( D [i] \) represents the distance from the root node to node i.

Here, and the difficulty of this question is that \ (set \) is used. Then remember to open \ (Long \) \ (Long. \)

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<map>
#include<set>
#define ll long long
#define IT set<node>::iterator
using namespace std;
inline int read(){
    int x=0,o=1;char ch=getchar();
    while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
    if(ch=='-')o=-1,ch=getchar();
    while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
    return x*o;
}
const int N=1e5+5;
ll ans,dis[N];
int n,m,tim,dfn[N],dep[N],f[N][25];
int tot,head[N],nxt[N<<1],to[N<<1],w[N<<1];
inline void add(int a,int b,int c){
    nxt[++tot]=head[a];head[a]=tot;
    to[tot]=b;w[tot]=c;
}
inline void dfs(int u,int fa){
    dfn[u]=++tim;
    for(int j=1;j<=20;++j)f[u][j]=f[f[u][j-1]][j-1];
    for(int i=head[u];i;i=nxt[i]){
        int v=to[i];if(v==fa)continue;
        dis[v]=dis[u]+w[i];f[v][0]=u;
        dep[v]=dep[u]+1;dfs(v,u);
    }
}
inline int LCA(int x,int y){
    if(dep[x]<dep[y])swap(x,y);
    for(int j=20;j>=0;--j)if(dep[f[x][j]]>=dep[y])x=f[x][j];
    if(x==y)return x;
    for(int j=20;j>=0;--j)if(f[x][j]!=f[y][j])x=f[x][j],y=f[y][j];
    return f[x][0];
}
struct node{
    int u,v;
    bool operator <(const node &x)const{
        return v<x.v;
    }
};set<node>s;
inline node get_pre(IT x){
    if(x==s.begin())return *(--s.end());
    return *(--x);
}
inline node get_nxt(IT x){
    if(x==--s.end())return *(s.begin());
    return *(++x);
}
inline ll get_ans(int x,int y){return dis[x]+dis[y]-2*dis[LCA(x,y)];}
int main(){
    n=read();
    for(int i=1;i<n;++i){
        int a=read(),b=read(),c=read();
        add(a,b,c);add(b,a,c);
    }
    dfs(1,0);m=read();
    for(int i=1;i<=m;++i){
        char ch;cin>>ch;
        if(ch=='+'){
            int x=read();IT it=s.insert((node){x,dfn[x]}).first;
            int pre=(get_pre(it)).u,nxt=(get_nxt(it)).u;
            ans+=get_ans(((node)*it).u,pre)+get_ans(((node)*it).u,nxt)-get_ans(pre,nxt);
        }
        else if(ch=='-'){
            int x=read();IT it=s.find((node){x,dfn[x]});
            int pre=(get_pre(it)).u,nxt=(get_nxt(it)).u;
            ans-=get_ans(((node)*it).u,pre)+get_ans(((node)*it).u,nxt)-get_ans(pre,nxt);
            s.erase(it);
        }
        else if(ch=='?')printf("%lld\n",ans/2);
    }
    return 0;
}

\ ([SDOI2015] \) treasure hunt this question, the input format is a bit different, the final answer is not divided by two, because the problem is to put together all the nodes vision stone, but this problem is to traverse all nodes some treasures Finally, return to the starting node, each side would have to go up twice.

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<map>
#include<set>
#define ll long long
#define IT set<node>::iterator
using namespace std;
inline int read(){
    int x=0,o=1;char ch=getchar();
    while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
    if(ch=='-')o=-1,ch=getchar();
    while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
    return x*o;
}
const int N=1e5+5;
ll ans,dis[N];
int n,m,tim,dfn[N],dep[N],bj[N],f[N][25];
int tot,head[N],nxt[N<<1],to[N<<1],w[N<<1];
inline void add(int a,int b,int c){
    nxt[++tot]=head[a];head[a]=tot;
    to[tot]=b;w[tot]=c;
}
inline void dfs(int u,int fa){
    dfn[u]=++tim;
    for(int j=1;j<=20;++j)f[u][j]=f[f[u][j-1]][j-1];
    for(int i=head[u];i;i=nxt[i]){
        int v=to[i];if(v==fa)continue;
        dis[v]=dis[u]+w[i];f[v][0]=u;
        dep[v]=dep[u]+1;dfs(v,u);
    }
}
inline int LCA(int x,int y){
    if(dep[x]<dep[y])swap(x,y);
    for(int j=20;j>=0;--j)if(dep[f[x][j]]>=dep[y])x=f[x][j];
    if(x==y)return x;
    for(int j=20;j>=0;--j)if(f[x][j]!=f[y][j])x=f[x][j],y=f[y][j];
    return f[x][0];
}
struct node{
    int u,v;
    bool operator <(const node &x)const{
        return v<x.v;
    }
};set<node>s;
inline node get_pre(IT x){
    if(x==s.begin())return *(--s.end());
    return *(--x);
}
inline node get_nxt(IT x){
    if(x==--s.end())return *(s.begin());
    return *(++x);
}
inline ll get_ans(int x,int y){return dis[x]+dis[y]-2*dis[LCA(x,y)];}
int main(){
    n=read();m=read();
    for(int i=1;i<n;++i){
        int a=read(),b=read(),c=read();
        add(a,b,c);add(b,a,c);
    }
    dfs(1,0);
    for(int i=1;i<=m;++i){
        int x=read();
        if(!bj[x]){//标记数组,判断是否出现过,没出现过就插入
            IT it=s.insert((node){x,dfn[x]}).first;
            int pre=(get_pre(it)).u,nxt=(get_nxt(it)).u;
            ans+=get_ans(((node)*it).u,pre)+get_ans(((node)*it).u,nxt)-get_ans(pre,nxt);
            bj[x]=1;
        }
        else{//出现过就删除
            IT it=s.find((node){x,dfn[x]});
            int pre=(get_pre(it)).u,nxt=(get_nxt(it)).u;
            ans-=get_ans(((node)*it).u,pre)+get_ans(((node)*it).u,nxt)-get_ans(pre,nxt);
            s.erase(it);bj[x]=0;
        }
        printf("%lld\n",ans);
    }
    return 0;
}

Guess you like

Origin www.cnblogs.com/PPXppx/p/11572324.html