Autostrady

https://szkopul.edu.pl/problemset/problem/f2dSBM7JteWHqtmVejMWe1bW/site/?key=statement

题意:

  首先给定一棵树,除了n-1条树边以外,还有m条非树边。每次询问两个点的满足以下条件的路径条数。

  1. 不能走树上u到v的简单路径的边。
  2. 只能走一条非树边。

分析:

  RMQ求LCA + 线段树合并。

  问题转化为有多少边的一个端点在u的子树内,另一个在v的子树内。

  每个询问只在深度大的询问加入深度小的。对每个节点建立一个权值线段树,dfs从叶子节点往上合并,每到一个节点询问一段区间的数。

  如果询问一个是另一个的祖先,要特判。

代码:

 #include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<iostream>
#include<cctype>
#include<set>
#include<vector>
#include<queue>
#include<map>
#define pa pair<int,int>
#define mp(a,b) make_pair(a,b)
using namespace std;
typedef long long LL; inline int read() {
int x=,f=;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-;
for(;isdigit(ch);ch=getchar())x=x*+ch-'';return x*f;
} const int N = ; int deth[N], id[N], siz[N], ans[N * ], Time_Index, n; // ans[N * 5] !!!
vector<int> adj[N], ext[N];
vector< pa > q[N]; namespace LCA{
int ord[N << ], d[N << ], p[N], f[N << ][], Log[N << ], tot = ;
void dfs(int u,int fa,int dep) {
ord[++ tot] = u; d[tot] = dep;
p[u] = tot;
for (int i=,sz=adj[u].size(); i<sz; ++i) {
int v = adj[u][i];
if (v == fa) continue;
dfs(v, u, dep + );
ord[++tot] = u; d[tot] = dep;
}
}
void init() {
Log[] = -;
for (int i=; i<=tot; ++i)
f[i][] = i, Log[i] = Log[i >> ] + ; // i<<1 !!!
for (int j=; j<=Log[tot]; ++j) {
for (int i=; (i+(<<j)-)<=tot; ++i) {
int x = f[i][j - ], y = f[i+(<<(j-))][j - ]; // j-1 !!!
f[i][j] = d[x] < d[y] ? x : y;
}
}
}
int Lca(int u,int v) {
u = p[u], v = p[v];
if (u > v) swap(u, v);
int k = Log[v - u + ];
int x = f[u][k], y = f[v-(<<k)+][k];
return d[x] < d[y] ? ord[x] : ord[y];
}
void Main() {
tot = ; dfs(, , ); init();
}
} namespace SegmentTree{
queue<int> s;
int sum[N * ], ls[N * ], rs[N * ], tot;
int NewNode() {
int k;
if (!s.empty()) k = s.front(), s.pop();
else k = ++tot;
sum[k] = ls[k] = rs[k] = ;
return k;
}
void Insert(int l,int r,int &rt,int p) {
if (!rt) rt = NewNode();
if (l == r) {
sum[rt] ++; return ;
}
int mid = (l + r) >> ;
if (p <= mid) Insert(l, mid, ls[rt], p);
else Insert(mid + , r, rs[rt], p);
sum[rt] = sum[ls[rt]] + sum[rs[rt]];
}
int query(int l,int r,int rt,int L,int R) {
if (!rt) return ; // !!!
if (L <= l && r <= R) return sum[rt];
int mid = (l + r) >> , res = ;
if (L <= mid) res = query(l, mid, ls[rt], L, R);
if (R > mid) res += query(mid + , r, rs[rt], L, R);
return res;
}
int Merge(int x,int y) {
if (!x || !y) return x + y;
ls[x] = Merge(ls[x], ls[y]);
rs[x] = Merge(rs[x], rs[y]);
sum[x] = sum[x] + sum[y]; // sum[x] = sum[ls[x]] + sum[rs[x]]; !!!
s.push(y);
return x;
}
int solve(int u,int fa) {
int rt = NewNode();
for (int i=,sz=adj[u].size(); i<sz; ++i)
if (adj[u][i] != fa) rt = Merge(rt, solve(adj[u][i], u));
for (int i=,sz=ext[u].size(); i<sz; ++i)
Insert(, n, rt, id[ext[u][i]]);
for (int i=,sz=q[u].size(); i<sz; ++i) {
int v = q[u][i].first;
if (LCA::Lca(u, v) == v) {
for (int t,j=; j<adj[v].size(); ++j)
if ((t=adj[v][j]) == LCA::Lca(u, t) && deth[t] > deth[v]) {// deth[t] > deth[v] !!!
ans[q[u][i].second] = query(, n, rt, , n) - query(, n, rt, id[t], id[t] + siz[t] - );
break;
}
}
else ans[q[u][i].second] = query(, n, rt, id[v], id[v] + siz[v] - );
}
return rt;
}
}
void dfs(int u,int fa) {
deth[u] = deth[fa] + ;
siz[u] = ;
id[u] = ++Time_Index;
for (int i=,sz=adj[u].size(); i<sz; ++i) {
int v = adj[u][i];
if (v == fa) continue;
dfs(v, u);
siz[u] += siz[v];
}
} int main() {
n = read();
for (int i=; i<n; ++i) {
int u = read(), v = read();
adj[u].push_back(v), adj[v].push_back(u);
}
int m = read();
for (int i=; i<=m; ++i) {
int u = read(), v = read();
ext[u].push_back(v), ext[v].push_back(u);
}
dfs(, );
int Q = read();
for (int i=; i<=Q; ++i) {
int u = read(), v = read();
if (deth[u] > deth[v]) q[u].push_back(mp(v,i));
else q[v].push_back(mp(u, i));
}
LCA::Main();
SegmentTree::solve(, );
for (int i=; i<=Q; ++i)
printf("%d\n", ans[i] + );
return ;
}

ONTAK 2010 aut的更多相关文章

  1. 【BZOJ 3545】【ONTAK 2010】Peaks & 【BZOJ 3551】【ONTAK 2010】Peaks加强版 Kruskal重构树

    sunshine的A题我竟然调了一周!!! 把循环dfs改成一个dfs就可以,,,我也不知道为什么这样就不会RE,但它却是A了,,, 这周我一直在调这个题,总结一下智障错误: 1.倍增的范围设成了n而 ...

  2. OI知识点/得分技巧的归纳总结

    网络流 拆点/拆边技巧 题目来源 bzoj1070 题目描述 同一时刻有\(N\)位车主带着他们的爱车来到了汽车维修中心.维修中心共有\(M\)位技术人员,不同的技术人员对不同 的车进行维修所用的时间 ...

  3. 如何使用本地账户"完整"安装 SharePoint Server 2010+解决“New-SPConfigurationDatabase : 无法连接到 SharePoint_Config 的 SQL Server 的数据 库 master。此数据库可能不存在,或当前用户没有连接权限。”

    注:目前看到的解决本地账户完整安装SharePoint Server 2010的解决方案如下,但是,有但是的哦: 当我们选择了"完整"模式安装SharePointServer201 ...

  4. How to accept Track changes in Microsoft Word 2010?

    "Track changes" is wonderful and remarkable tool of Microsoft Word 2010. The feature allow ...

  5. [入门级] 基于 visual studio 2010 mvc4 的图书管理系统开发初步 (二)

    [入门级] 基于 visual studio 2010 mvc4 的图书管理系统开发初步 (二) Date  周六 10 一月 2015 By 钟谢伟 Category website develop ...

  6. [入门级] visual studio 2010 mvc4开发,用ibatis作为数据库访问媒介(一)

    [入门级] visual studio 2010 mvc4开发,用ibatis作为数据库访问媒介(一) Date  周二 06 一月 2015 By 钟谢伟 Tags mvc4 / asp.net 示 ...

  7. c++ builder 2010 错误 F1004 Internal compiler error at 0x9740d99 with base 0x9

    今天遇到一个奇怪的问题,拷贝项目后,在修改,会出现F1004 Internal compiler error at 0x9740d99 with base 0x9 ,不管怎么改,删除改动,都没用,关闭 ...

  8. Sharepoint 2010、Sharepoint 2013浏览器打开CAD(.dwg)

    客户端配置 1.安装FreeDWGViewer.exe,设置浏览器查看 2.检查ActiveX插件是否已安装成功 服务端配置 1.开启许可模式或者通过脚本将"application/acad ...

  9. Microsoft Windows* SDK May 2010 或较新版本(兼容 2010 年 6 月 DirectX SDK)GPU Detect

    原文链接 下载代码样本 特性/描述 日期: 2016 年 5 月 5 日 GPU Detect 是一种简短的示例,演示了检测系统中主要显卡硬件(包括第六代智能英特尔® 酷睿™ 处理器产品家族)的方式. ...

随机推荐

  1. 浅聊IOC

    1.概述 IOC:有很多人把控制反转和依赖注入混为一谈,虽然在某种意义上来看他们是一体的,但好像又有些不同. 1. IOC(控制反转)是一个控制容器,DI(依赖注入)就是这个容器的运行机制. 2. I ...

  2. 用python实现矩阵转置

    前几天群里有同学提出了一个问题:手头现在有个列表,列表里面两个元素,比如[1, 2],之后不断的添加新的列表,往原来相应位置添加.例如添加[3, 4]使原列表扩充为[[1, 3], [2, 4]],再 ...

  3. [USACO19JAN]Exercise Route

    题目 这题的数据有点水,暴力合并\(set\)好像过了 分析一下这个题的性质,发现我们一条非树边就会形成一个环,而我们要求选择两个非树边,就会形成两个环,要求不走重复的点,就是说我们需要走一个大环,且 ...

  4. SSH框架——(二)四层结构:DAO,Service,Controller,View层

    1. DAO层: 主要任务:做数据持久层的工作,负责与数据库进行联络的一些任务都封装在此. DAO层的设计:首先是设计DAO层的接口,然后再Spring的配置文件中定义此接口的实现类,然后就可以在模块 ...

  5. 关于iOS 3D touch 指纹验证的随笔

    file:///Users/OWen/Desktop/3DTouch.png 随着iOS系统不断的更新迭代,苹果总会推出一些新的功能,今天就研究了一下iOS8之后推出的指纹验证的功能,然后写了一个小d ...

  6. Xcode菜单功能中文翻译

    Xcode菜单功能中文翻译 File  文件 Edit  编辑 View 视图 Navigate 导航 Editor 编辑 Product 产品 Window  窗口 Help 帮助 File  文件 ...

  7. 极光推送能获取 registrationId,但是接收不到通知 - iOS

    集成极光推送进行调试的时候,运行 App 可以正常获取 registrationId,但是却迟迟无法收到推送消息,而Android 端是可以正常收到消息; 检查了证书配置和极光的配置一切正常,便开始返 ...

  8. chromium之observer_list

    典型用法如下 /////////////////////////////////////////////////////////////////////////////// // // OVERVIE ...

  9. Ubuntu 16.04 搭建 ELK

    1.安装Java JDK sudo apt-get install default-jdk 2.安装Elasticsearch 1.导入Elasticsearch的GPG公钥 wget -qO - h ...

  10. diff命令--比较两个文件的命令

    可以使用 --brief 来比较两个文件是否相同,使用 -c参数来比较这两个文件的详细不同之处,这绝对是判断文件是否被篡改的有力神器,