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;
}
/* */

  

2015 Multi-University Training Contest 1 - 1009 Annoying problem的更多相关文章

  1. 2015 Multi-University Training Contest 5 1009 MZL's Border

    MZL's Border Problem's Link: http://acm.hdu.edu.cn/showproblem.php?pid=5351 Mean: 给出一个类似斐波那契数列的字符串序列 ...

  2. 2014 Multi-University Training Contest 9#1009

    Just a JokeTime Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others) Tot ...

  3. hdu 6394 Tree (2018 Multi-University Training Contest 7 1009) (树分块+倍增)

    链接: http://acm.hdu.edu.cn/showproblem.php?pid=6394 思路:用dfs序处理下树,在用分块,我们只需要维护当前这个点要跳出这个块需要的步数和他跳出这个块去 ...

  4. HDU 4608 I-number 2013 Multi-University Training Contest 1 1009题

    题目大意:输入一个数x,求一个对应的y,这个y满足以下条件,第一,y>x,第二,y 的各位数之和能被10整除,第三,求满足前两个条件的最小的y. 解题报告:一个模拟题,比赛的时候确没过,感觉这题 ...

  5. 2015 Multi-University Training Contest 9-1007 Travelling Salesman Problem

    Problem Description Teacher Mai is in a maze with n rows and m columns. There is a non-negative numb ...

  6. ACM多校联赛7 2018 Multi-University Training Contest 7 1009 Tree

    [题意概述] 给一棵以1为根的树,树上的每个节点有一个ai值,代表它可以传送到自己的ai倍祖先,如果不存在则传送出这棵树.现在询问某个节点传送出这棵树需要多少步. [题解] 其实是把“弹飞绵羊”那道题 ...

  7. 2019 Multi-University Training Contest 2 - 1009 - 回文自动机

    http://acm.hdu.edu.cn/showproblem.php?pid=6599 有好几种实现方式,首先都是用回文自动机统计好回文串的个数. 记得把每个节点的cnt加到他的fail上,因为 ...

  8. 2019 Multi-University Training Contest 1 - 1009 - String - 贪心

    不知道错在哪里. 是要把atop改成stop!两个弄混了.感谢自造样例. #include<bits/stdc++.h> using namespace std; typedef long ...

  9. 2015 Multi-University Training Contest 3 hdu 5324 Boring Class

    Boring Class Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Tota ...

随机推荐

  1. Hadoop - Mac OSX下配置和启动hadoop以及常见错误解决

    0. 安装JDK 参考网上教程在OSX下安装jdk 1. 下载及安装hadoop a) 下载地址: http://hadoop.apache.org b) 配置ssh环境 在terminal里面输入: ...

  2. transmission简单使用

    1.安装transmission-daemon sudo apt-get install transmission-daemon 2.设置用户名和密码并打开远程连接 a). 打开文件vim /var/ ...

  3. 【LeetCode】264. Ugly Number II

    Ugly Number II Write a program to find the n-th ugly number. Ugly numbers are positive numbers whose ...

  4. android开发出现No Launcher activity found!解决方案

    在AndroidManifest.xml中的中少了这段代码 <activity android:name=".MainActivity" android:label=&quo ...

  5. [转] Linux学习之CentOS(三十六)--FTP服务原理及vsfptd的安装、配置

    本篇随笔将讲解FTP服务的原理以及vsfptd这个最常用的FTP服务程序的安装与配置... 一.FTP服务原理 FTP(File Transfer Protocol)是一个非常古老并且应用十分广泛的文 ...

  6. Android 6.0 源代码编译实践

    http://www.judymax.com/archives/1087 Android 6.0 源代码编译实践 https://mirrors.tuna.tsinghua.edu.cn/help/A ...

  7. [原创]Java中的字符串比较,按照使用习惯进行比较

    java中的字符串比较一般可以采用compareTo函数,如果a.compareTo(b)返回的是小于0的数,那么说明a的unicode编码值小于b的unicode编码值. 但是很多情况下,我们开发一 ...

  8. HighCharts官网更新了!(忠实粉的小声音)

    之前用HighCharts做统计分析,用到的大部分都是柱状图和饼图,可是在HighCharts主页却摆着一个曲线图的实例,虽然从曲线图上的标记可以找到对应的API项,但是总是可能有对应不上柱状图的时候 ...

  9. 旧文—冬日感怀

    冬日感怀   下雪了,虽不大,可那雪花落在手上,融在心里,便泛起淡淡的温柔,因为这是冬日的馈赠啊,是上苍的礼物,是往昔记忆的灰烬化作天地间的精灵装点纷繁琐碎的世界.于是,透过汽车上雾气氤氲的玻璃窗,人 ...

  10. [AX2012 R3]关于Named user license report

    Named user license报表是用来统计各种授权类型用户数的,这里来看看报表数据具体是如何来的.这是一个SSRS的报表,最主要的数据源是来自于类SysUserLicenseCountRepo ...