正题

题目链接:https://www.luogu.com.cn/problem/P5180


题目大意

给出\(n\)个点的一张有向图,求每个点支配的点数量。

\(1\leq n\leq 2\times 10^5,1\leq m\leq 3\times 10^5\)


解题思路

首先定义半支配点\(semi_x\)表示对于点\(x\)寻找一个\(dfn\)序最小的点\(y\)满足存在一条\(y\)到\(x\)的路径去掉头尾之后所有点的\(dfn\)序都大于\(x\)的。

考虑怎么求每个点的半支配点,考虑两种情况对于一个能够直接到达\(x\)的点\(y\)

  1. \(dfn_y<dfn_x\):那么\(y\)可能是\(x\)的半支配点
  2. \(dfn_y>dfn_x\):那么设\(v\)表示\(y\)到\(dfs\)根节点的路径上的某个点\(u\)的\(dfn\)序最小的半支配点,那么\(v\)可能是\(u\)的半支配点

主要是第二种情况我们相当于要找一个在某个点到根节点路径上的点使得它的半支配点\(dfn\)序最小。

那么可以考虑倒序枚举,然后用带权并查集维护那个半支配点编号最小的。

之后就是半支配点有什么用,大概就是半支配点向点连边那么新的图支配关系不变。

所以一种暴力的做法就是直接跑\(DAG\)的支配树求法,但是有更快的。

考虑对于一个点\(x\)和它的半支配点\(y\),如果\(y\)到\(x\)的路径上我们找到一个半支配点\(dfn\)序最小的节点\(u\)且它的半支配点为\(v\)。

那么如果

  1. \(v=y\),那么证明整条路径上没有\(dfn\)序更小的半支配点,\(y\)就是\(x\)的支配点。
  2. \(d_u>d_y\),那么显然\(u\)有更小的支配点支配这套路径,所以\(u\)的支配点就是\(y\)的支配点

这个过程中\(u\)和\(v\)的维护和上面一样,所以可以一起求解。

但是我们可以暂时不知道\(u\)的支配点,所以可以先记录,最后在正序的记回去。

时间复杂度\(O(n\alpha(n))\)


code

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=2100;
struct node{
int l,r;
}q[110000];
int n,m,k,t,ans,p[N],st[N][26],ss[N][26],nxt[N],f[N][N],pre[N][N];
char T[N],S[N];
bool cmp(node x,node y)
{return x.l<y.l;}
int main()
{
freopen("lcs.in","r",stdin);
freopen("lcs.out","w",stdout);
scanf("%s",T+1);m=strlen(T+1);
scanf("%s",S+1);n=strlen(S+1);
for(int i=1;i<=m;i++){
for(int j=0;j<26;j++)
st[i][j]=st[i-1][j]+(T[i]=='a'+j);
}
for(int i=1;i<=n;i++){
for(int j=0;j<26;j++)
ss[i][j]=ss[i-1][j]+(S[i]=='a'+j);
}
scanf("%d",&k);
for(int i=1;i<=k;i++)
scanf("%d%d",&q[i].l,&q[i].r),q[i].l++,q[i].r++;
sort(q+1,q+1+k,cmp);
int nowr=0,pr=0;
for(int i=1;i<=k;i++){
if(q[i].l>nowr){
nxt[pr]=nowr;
for(int j=nowr+1;j<q[i].l;j++)nxt[j]=j;
pr=q[i].l;nowr=q[i].r;
}
else nowr=max(q[i].r,nowr);
}
nxt[pr]=nowr;
for(int i=nowr+1;i<=n;i++)nxt[i]=i;
for(int i=1;i<=n;i++)
if(nxt[i])p[++t]=i;
for(int i=1;i<=m;i++)
for(int j=1;j<=t;j++){
int l=p[j],r=nxt[l],L=i;
for(int z=min(r-l,m-L);z>=0;z--){
bool flag=1;
for(int k=0;k<26;k++)
if(ss[r][k]-ss[l-1][k]<st[L+z][k]-st[L-1][k])
{flag=0;break;}
if(flag){pre[i][j]=z+1;break;}
}
}
for(int i=1;i<=m;i++)
for(int j=1;j<=t;j++){
int l=p[j],r=nxt[l],R=i;
if(pre[i][j]==r-l+1)continue;
for(int z=min(r-l,R-1)-1;z>=0;z--){
bool flag=1;
for(int k=0;k<26;k++)
if(ss[r][k]-ss[l-1][k]<st[R][k]-st[R-z-1][k])
{flag=0;break;}
if(flag){f[i+1][j+1]=z+1;ans=max(ans,z+1);break;}
}
}
for(int i=1;i<=m;i++)
for(int j=1;j<=t;j++){
int l=p[j],r=nxt[l];
if(pre[i][j]==r-l+1){
f[i+r-l+1][j+1]=max(f[i+r-l][j+1],f[i][j]+r-l+1);
ans=max(ans,f[i][j]+r-l+1);
}
ans=max(ans,f[i][j]+pre[i][j]);
}
printf("%d\n",ans);
return 0;
}

P5180-[模板]支配树的更多相关文章

  1. [HDU]4694 Important Sisters(支配树)

    支配树模板 #include<cstdio> #include<cstring> #include<algorithm> using namespace std; ...

  2. P3384 【模板】树链剖分

    P3384 [模板]树链剖分 题目描述 如题,已知一棵包含N个结点的树(连通且无环),每个节点上包含一个数值,需要支持以下操作: 操作1: 格式: 1 x y z 表示将树从x到y结点最短路径上所有节 ...

  3. 洛谷P3368 【模板】树状数组 2

    P3368 [模板]树状数组 2 102通过 206提交 题目提供者HansBug 标签 难度普及/提高- 提交  讨论  题解 最新讨论 暂时没有讨论 题目描述 如题,已知一个数列,你需要进行下面两 ...

  4. 洛谷P3374 【模板】树状数组 1

    P3374 [模板]树状数组 1 140通过 232提交 题目提供者HansBug 标签 难度普及/提高- 提交  讨论  题解 最新讨论 题目描述有误 题目描述 如题,已知一个数列,你需要进行下面两 ...

  5. hdu 1754 I Hate It (模板线段树)

    http://acm.hdu.edu.cn/showproblem.php?pid=1754 I Hate It Time Limit: 9000/3000 MS (Java/Others)    M ...

  6. 康复计划#4 快速构造支配树的Lengauer-Tarjan算法

    本篇口胡写给我自己这样的老是证错东西的口胡选手 以及那些想学支配树,又不想啃论文原文的人- 大概会讲的东西是求支配树时需要用到的一些性质,以及构造支配树的算法实现- 最后讲一下把只有路径压缩的并查集卡 ...

  7. luogu3384 【模板】树链剖分

    P3384 [模板]树链剖分 题目描述 如题,已知一棵包含N个结点的树(连通且无环),每个节点上包含一个数值,需要支持以下操作: 操作1: 格式: 1 x y z 表示将树从x到y结点最短路径上所有节 ...

  8. luogu2597-[ZJOI2012]灾难 && DAG支配树

    Description P2597 [ZJOI2012]灾难 - 洛谷 | 计算机科学教育新生态 Solution 根据题意建图, 新建一个 \(S\) 点, 连向每个没有入边的点. 定义每个点 \( ...

  9. HDU.4694.Important Sisters(支配树)

    HDU \(Description\) 给定一张简单有向图,起点为\(n\).对每个点求其支配点的编号和. \(n\leq 50000\). \(Solution\) 支配树. 还是有点小懵逼. 不管 ...

随机推荐

  1. windows10右键我的电脑,点击管理,提示该文件没有与之关联的应用来执行该操作,请安装应用,若已经安装应用,请在默认应用设置页面中创建关联……

    方法一 1.按WIN+R 调出运行对话框,然后输入bai gpedit.msc 回车:2.展开"计du算机配置"zhi-"Windows设置"-"安全 ...

  2. Longhorn,企业级云原生容器分布式存储 - 定制默认设置

    内容来源于官方 Longhorn 1.1.2 英文技术手册. 系列 Longhorn 是什么? Longhorn 云原生容器分布式存储 - 设计架构和概念 Longhorn 云原生容器分布式存储 - ...

  3. wpf 实现印章,公章效果

    能写一些特定外观的控件,是一个做界面开发的程序员的基础技能.基本上,不管你是做web,QT,MFC,Winform,WPF等等,如果自己看到一个比较好看的有趣的效果,能大致推断出它的实现方式并照猫画虎 ...

  4. Object--Date--calendar--System--StringBuilder--基本数据类型包装类型

    Object java.lang.Object类是Java语言中的根类,即所有类的父类 默认toString()方法打印的是对象在堆中的地址值 默认equals()方法比较的也是地址(String中对 ...

  5. 使用元数据设计的update、query封装

    package util; import java.lang.reflect.InvocationTargetException; import java.sql.Connection; import ...

  6. 786. 第k个数

    题目传送门 一.理解感悟 1.这是快速排序模板的练习题. 2.不一样的地方在于它可以利用快排模板,但却不需要真的把所有数据排序完成,每次一分为二后,只关心自己所有的那一半,就是可以节约一半的递归. 3 ...

  7. Java的Class类及static块的执行时机

    要理解RTTI在Java中的工作原理,首先必须知道类型信息在运行时是如何表示的,这项工程由Class对象完成,它包含了与类有关的信息.Java使用Class对象来执行其RTTI,即使你执行的是类似转型 ...

  8. DNS重新绑定攻击

    来自微信外挂的安全风险 DNS重新绑定攻击 DDNS 动态域名设置

  9. hyperf从零开始构建微服务(一)——构建服务提供者

    阅读目录 什么是服务 构建服务提供者 1.创建数据表 2.构建服务提供者 3.安装json rpc依赖 4.安装rpc server组件 5.修改server配置 6.配置数据库 7.编写基础代码 7 ...

  10. Python - 如何将 list 列表作为数据结构使用

    列表作为栈使用 栈的特点 先进后出,后进先出 如何模拟栈? 先在堆栈尾部添加元素,使用 append() 然后从堆栈顶部取出一个元素,使用 pop() # 模拟栈 stack = [1, 2, 3, ...