Description

Solution

由于题目要求,将a[i]->b[i](边权为i)后所得的图应该是由森林和环套树组合而成。

假如是树形结构,所有的t[i]就直接在线段树t[i]点的dfs序(即in[t[i]],out[t[i]]区间)处记录t[i]点的深度。

这样,针对所有的f[i],在线段树上查找所有包含in[f[i]]点的区间所记录的最大深度d。(这个深度就是在离f[i]最近并且已经验证了是真命题的祖先的深度)

然后用倍增算出f[i]向上到深度d,所经过的编号最大值c。ans=min(ans,c)。

原因:ans是指,图中存在a[i]->b[i](1<=i<=ans)时该询问刚好出现矛盾。如果ans-=1,则所有的f[i]都无法到达离它最近的并且已经验证了是真命题的祖先点。

环套树结构:我们把环拆成树

其中Ca->Cb的边权还是a->b边的边权。以此类推其他都是这样。(原本环套树上以a,b,c,d,e为根的树还是以a,b,c,d,e为根)如此,假如说t[i]在环上,我们除了在in[t[i]],out[t[i]]区间记录t[i]点的深度,还要在in[C(t[i])],out[C(t[i])]区间记录C(t[i])点的深度。这样,不论是原本以t[i]为根的子树,还是环上的以其他点为根的树的信息都可以更新完毕。

Code

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
const int N=2e5+;
int n,_n,m,Q,a,b;
int fa1[N<<],val[N<<],cir[N];
int tag[N];//0-not_visit 1-tag the stack 2-out the stack
int rt[N],cnt; int y[N<<],nxt[N<<],h[N<<],tot;
void link(int _x,int _y){y[++tot]=_y;nxt[tot]=h[_x];h[_x]=tot;}
void build(int u)
{
if (!fa1[u]){rt[++cnt]=u;tag[u]=;return;}
if (tag[fa1[u]]==)
{
int x=u;
for(int t=fa1[x];t!=u;t=fa1[t])
{
cir[t]=++n;val[n]=val[t];link(n,x);
fa1[x]=n;x=fa1[x];
}
cir[u]=++n;link(n,x);rt[++cnt]=n;
tag[u]=;
return;
}
tag[u]=;
if (!tag[fa1[u]]) build(fa1[u]);link(fa1[u],u);
tag[u]=;
}
int dfn,in[N<<],out[N<<],dep[N<<],fa[N<<][],mxe[N<<][];
void dfs(int x)
{
in[x]=++dfn;mxe[x][]=val[x];dep[x]=dep[fa[x][]]+;
for (int i=;i<=;i++)
{
fa[x][i]=fa[fa[x][i-]][i-];
mxe[x][i]=max(mxe[x][i-],mxe[fa[x][i-]][i-]);
}
for (int i=h[x];i;i=nxt[i]) fa[y[i]][]=x,dfs(y[i]);
out[x]=dfn;
}
int cur[N<<],mxd[N<<];
void modify(int k,int l,int r,int askx,int asky,int d)
{
if (askx<=l&&r<=asky){if (Q<cur[k]||mxd[k]<d) cur[k]=Q,mxd[k]=d;return;}
int mid=(l+r)/;
if (askx<=mid) modify(k<<,l,mid,askx,asky,d);
if (asky>mid) modify(k<<|,mid+,r,askx,asky,d);
}
int query(int k,int l,int r,int x)
{
int mid=(l+r)/,re=cur[k]==Q?mxd[k]:;
if (l==r) return re;
if (x<=mid) re=max(re,query(k<<,l,mid,x));else re=max(re,query(k<<|,mid+,r,x));
return re;
}
int t,f,ret,ref;
int main()
{
scanf("%d%d",&n,&m);_n=n;
for (int i=;i<=m;i++) {scanf("%d%d",&a,&b);fa1[b]=a;val[b]=i;}
for (int i=;i<=_n;i++) if (!tag[i]) build(i);
for (int i=;i<=cnt;i++) dfs(rt[i]);
scanf("%d",&Q);
while (Q--)
{
scanf("%d",&ret);
for (int i=;i<=ret;i++)
{
scanf("%d",&t),modify(,,n,in[t],out[t],dep[t]);
if (cir[t]) modify(,,n,in[cir[t]],out[cir[t]],dep[cir[t]]);
}
int ans=m+,d,c;
scanf("%d",&ref);
for (int i=;i<=ref;i++)
{
scanf("%d",&f);
d=query(,,n,in[f]);c=;
if (d==) continue;else d=dep[f]-d;
for(int j=;d;d>>=,j++)
if (d&) c=max(c,mxe[f][j]),f=fa[f][j];
ans=min(ans,c);
}
if (ans==m+) printf("OK\n");else printf("%d\n",ans);
}
}

[2016北京集训测试赛15]statement-[线段树+拆环]的更多相关文章

  1. [2016北京集训测试赛5]小Q与内存-[线段树的神秘操作]

    Description Solution 哇真的异常服气..线段树都可以搞合并和拆分的啊orzorz.神的世界我不懂 Code #include<iostream> #include< ...

  2. 2016北京集训测试赛(十七)Problem C: 数组

    Solution 线段树好题. 我们考虑用last[i]表示\(i\)这个位置的颜色的上一个出现位置. 考虑以一个位置\(R\)为右端点的区间最远能向左延伸到什么位置: \(L = \max_{i \ ...

  3. 2016北京集训测试赛(十六)Problem A: 任务安排

    Solution 这道题告诉我们, 不能看着数据范围来推测正解的时间复杂度. 事实证明, 只要常数足够小, \(5 \times 10^6\)也是可以跑\(O(n \log n)\)算法的!!! 这道 ...

  4. 【2016北京集训测试赛(十)】 Azelso (期望DP)

    Time Limit: 1000 ms   Memory Limit: 256 MB Description 题解 状态表示: 这题的状态表示有点难想...... 设$f_i$表示第$i$个事件经过之 ...

  5. 【2016北京集训测试赛(二)】 thr (树形DP)

    Description 题解 (这可是一道很早就碰到的练习题然后我不会做不想做,没想到在Contest碰到欲哭无泪......) 题目大意是寻找三点对的个数,使得其中的三个点两两距离都为d. 问题在于 ...

  6. 【2016北京集训测试赛(八)】 crash的数列 (思考题)

    Description 题解 题目说这是一个具有神奇特性的数列!这句话是非常有用的因为我们发现,如果套着这个数列的定义再从原数列引出一个新数列,它居然还是一样的...... 于是我们就想到了能不能用多 ...

  7. 【2016北京集训测试赛(十六)】 River (最大流)

    Description  Special Judge Hint 注意是全程不能经过两个相同的景点,并且一天的开始和结束不能用同样的交通方式. 题解 题目大意:给定两组点,每组有$n$个点,有若干条跨组 ...

  8. 【2016北京集训测试赛】river

    HINT 注意是全程不能经过两个相同的景点,并且一天的开始和结束不能用同样的交通方式. [吐槽] 嗯..看到这题的想法的话..先想到了每个点的度为2,然后就有点不知所措了 隐隐约约想到了网络流,但并没 ...

  9. 【2016北京集训测试赛】azelso

    [吐槽] 首先当然是要orzyww啦 以及orzyxq奇妙顺推很强qwq 嗯..怎么说呢虽然说之前零零散散做了一些概d的题目但是总感觉好像并没有弄得比较明白啊..(我的妈果然蒟蒻) 这题的话可以说是难 ...

随机推荐

  1. springboot 学习之路 17(webflux 入门 (1))

    Webflux: webflux是在springboot2系列引入的技术:补充一些概念: 1> Reactive Streams 是 JVM 中面向流的库标准和规范: 处理可能无限数量的元素 按 ...

  2. Centos 7 安装GNOME桌面环境

    第一步:列出可安装的桌面环境 [root@local ~]# yum grouplist 第二步:安装GNOME及相应桌面管理工具 [root@local ~]# yum group info &qu ...

  3. 控制台中寄宿WCF服务

    一.首先创建一个类库,用来定义WCF服务 修改服务代码定义,具体代码如下 // 注意: 使用"重构"菜单上的"重命名"命令,可以同时更改代码和配置文件中的接口名 ...

  4. python常用模块之logging模块

    #日志级别 : noset debug info warning error critical #控制台默认的级别是warning的. import logging logging.basicConf ...

  5. 使用 Azure PowerShell 监视和更新 Windows 虚拟机

    Azure 监视使用代理从 Azure VM 收集启动和性能数据,将此数据存储在 Azure 存储中,并使其可供通过门户.Azure PowerShell 模块和 Azure CLI 进行访问. 使用 ...

  6. AD RMS企业文件版权管理

    AD RMS (AD权限管理服务)能够确保企业内部数字文件的机密性,例如,用户即使有权限读取受保护的文件,但是如果未被许可,就无法复制与打印该文件. AD RMS概述 虽然可以通过NTFS权限来设置用 ...

  7. RHEL7.3安装mysql5.7

    RHEL7.3 install mysql5.7 CentOS7默认安装MariaDB而不是MySQL,而且yum服务器上也移除了MySQL相关的软件包.因为MariaDB和MySQL可能会冲突,需先 ...

  8. CentOS7 配置静态 ip

    1. 为 CentOS7 配置静态 ip 1.1 修改文件/etc/sysconfig/network-scripts/ifcfg-ens33 sudo vi /etc/sysconfig/netwo ...

  9. python3: 数字日期和时间(1)

    ---恢复内容开始--- 1. 数字的四舍五入 Q: 你想对浮点数执行指定精度的舍入运算 A: 简单的使用内置的round(value, ndigits)函数即可. >>> roun ...

  10. 死磕nginx系列--使用nginx做负载均衡

    使用nginx做负载均衡的两大模块: upstream 定义负载节点池. location 模块 进行URL匹配. proxy模块 发送请求给upstream定义的节点池. upstream模块解读 ...