2015 Multi-University Training Contest 1 - 1009 Annoying problem

简介:  Annoying problem Problem's Link:  http://acm.hdu.edu.cn/showproblem.php?pid=5296     Mean:  给你一个有根树和一个节点集合S,初始S为空,有q个操作,每个操作要么从树中选一个结点加入到S中(不删除树中节点),要么从S集合中删除一个结点。

 Annoying problem

Problem's Link:  http://acm.hdu.edu.cn/showproblem.php?pid=5296  


 

Mean: 

给你一个有根树和一个节点集合S,初始S为空,有q个操作,每个操作要么从树中选一个结点加入到S中(不删除树中节点),要么从S集合中删除一个结点。你需要从树中选一些边组成集合E,E中的边能够是S中的节点连通。对于每一个操作,输出操作后E中所有边的边权之和。

analyse:

首先是构图,把树看作一个无向图,使用邻接表存图。

处理出从1号结点的dfs序存储起来。

添加点u操作:查找S集合中的点与添加的点dfs序在前面且编号最大的点,以及dfs序在后面且编号最小的点,设这两个点是x,y。

那么增加的花费是:dis[u]-dis[lca[(x,u)] - dis [lca(y,u)] + dis[lca(x,y) ]; 其中dis代表该点到根节点的距离。

 

对于删除点u操作:先把点从集合中删除,然后再计算减少花费,计算公式和增加的计算方法一样。

也是看了题解才撸出来的。

Time complexity: O(N)

 

Source code: 

/*
* this code is made by crazyacking
* Verdict: Accepted
* Submission Date: 2015-07-22-11.22
* Time: 0MS
* Memory: 137KB
*/
#include <queue>
#include <cstdio>
#include <set>
#include <string>
#include <stack>
#include <cmath>
#include <climits>
#include <map>
#include <cstdlib>
#include <iostream>
#include <vector>
#include <algorithm>
#include <cstring>
#define  LL long long
#define  ULL unsigned long long
#define rep(i,n) for(int i=0;i<n;++i)
using namespace std;

const int N = 100010,D=20;
int st[N], ori[N], dfs_clock;
vector<pair<int, int> > G[N];
int shortcut[D][N], dep[N];
int *fa;
int get_lca( int a, int b )
{
      if( dep[a] < dep[b] )
            swap( a, b );
      for( int i = D - 1; ~i; --i )
      {
            if( dep[a] - dep[b] >> i & 1 )
                  a = shortcut[i][a];
      }
      if( a == b ) return a;
      for( int i = D - 1; ~i; --i )
      {
            if( shortcut[i][a] != shortcut[i][b] )
            {
                  a = shortcut[i][a];
                  b = shortcut[i][b];
            }
      }
      return fa[a];
}

int dis[N];
void dfs( int u, int father )
{
      st[u] = ++dfs_clock;
      ori[dfs_clock] = u;
      vector<pair<int, int> > :: iterator it;
      for( it = G[u].begin(); it != G[u].end(); ++it )
      {
            int v = ( *it ).first;
            int w = ( *it ).second;
            if( v == father )continue;
            fa[v] = u;
            dep[v] = dep[u] + 1;
            dis[v] = dis[u] + w;
            dfs( v, u );
      }
}


void prepare( int n )
{
      for( int j = 1; j < D; ++j )
      {
            rep( i, n )
            {
                  int &res = shortcut[j][i];
                  res = shortcut[j - 1][i];
                  if( ~res ) res = shortcut[j - 1][res];
            }
      }
}


set<int> nodes;
int get_dis( int a, int b )
{
      return dis[a] + dis[b] - 2 * dis[get_lca( a, b )];
}


int add( int u )
{
      if( !nodes.empty() )
      {
            set<int>::iterator low, high;
            low = nodes.lower_bound( st[u] );
            high = low;
            if( low == nodes.end() || low == nodes.begin() )
            {
                  low = nodes.begin();
                  high = nodes.end();
                  high--;
            }
            else low--;
            int x = ori[*low];
            int y = ori[*high];
            int res = get_dis( x, u ) + get_dis( y, u ) - get_dis( x, y );
            return res;
      }
      return 0;
}

int main()
{
      ios_base::sync_with_stdio( false );
      cin.tie( 0 );
      int T, n, q, u, v, w;
      scanf( "%d", &T );
      rep( cas, T )
      {
            scanf( "%d %d", &n, &q );
            rep( i, n ) G[i].clear();
            dfs_clock = 0;
            rep( i, n - 1 )
            {
                  scanf( "%d %d %d", &u, &v, &w );
                  u--;
                  v--;
                  G[u].push_back( make_pair( v, w ) );
                  G[v].push_back( make_pair( u, w ) );
            }
            fa = shortcut[0];
            fa[0] = -1;
            dfs( 0, -1 );
            prepare( n );
            nodes.clear();
            printf( "Case #%d:\n", cas + 1 );
            int ans = 0;
            while( q-- )
            {
                  int op;
                  scanf( "%d %d", &op, &u );
                  u--;
                  if( op == 1 )  // add
                  {
                        if( nodes.find( st[u] ) == nodes.end() )
                        {
                              ans += add( u );
                              nodes.insert( st[u] );
                        }
                  }
                  else   // delete
                  {
                        if( nodes.find( st[u] ) != nodes.end() )
                        {
                              nodes.erase( st[u] );
                              ans -= add( u );
                        }
                  }
                  printf( "%d\n", ans >> 1 );
            }
      }
      return 0;
}
/*

*/

  

目录
相关文章
|
2天前
|
数据采集 人工智能 安全
|
11天前
|
云安全 监控 安全
|
3天前
|
自然语言处理 API
万相 Wan2.6 全新升级发布!人人都能当导演的时代来了
通义万相2.6全新升级,支持文生图、图生视频、文生视频,打造电影级创作体验。智能分镜、角色扮演、音画同步,让创意一键成片,大众也能轻松制作高质量短视频。
1017 151
|
3天前
|
编解码 人工智能 机器人
通义万相2.6,模型使用指南
智能分镜 | 多镜头叙事 | 支持15秒视频生成 | 高品质声音生成 | 多人稳定对话
|
16天前
|
机器学习/深度学习 人工智能 自然语言处理
Z-Image:冲击体验上限的下一代图像生成模型
通义实验室推出全新文生图模型Z-Image,以6B参数实现“快、稳、轻、准”突破。Turbo版本仅需8步亚秒级生成,支持16GB显存设备,中英双语理解与文字渲染尤为出色,真实感和美学表现媲美国际顶尖模型,被誉为“最值得关注的开源生图模型之一”。
1711 9
|
8天前
|
人工智能 自然语言处理 API
一句话生成拓扑图!AI+Draw.io 封神开源组合,工具让你的效率爆炸
一句话生成拓扑图!next-ai-draw-io 结合 AI 与 Draw.io,通过自然语言秒出架构图,支持私有部署、免费大模型接口,彻底解放生产力,绘图效率直接爆炸。
654 152
|
10天前
|
人工智能 安全 前端开发
AgentScope Java v1.0 发布,让 Java 开发者轻松构建企业级 Agentic 应用
AgentScope 重磅发布 Java 版本,拥抱企业开发主流技术栈。
620 12
|
10天前
|
人工智能 自然语言处理 API
Next AI Draw.io:当AI遇见Draw.io图表绘制
Next AI Draw.io 是一款融合AI与图表绘制的开源工具,基于Next.js实现,支持自然语言生成架构图、流程图等专业图表。集成多款主流大模型,提供智能绘图、图像识别优化、版本管理等功能,部署简单,安全可控,助力技术文档与系统设计高效创作。
690 151