【NOIP2016提高A组模拟9.15】Map
题目
分析
发现,当原图是一棵树的时候,那么新建一条边后,就会变成环套树,
而环内的所有点对都是安全点对,如果环中有k个点,答案就是\(k(k-1)\)
联想到,当把原图做一遍tarjan缩点,每个环缩成一个点,点权为环中的点数,然后就变成了一棵树,那么新建一条边后,就会变成环套树,
经过计算,增加的点对数就是点权和的平方减去点权的平方和
至于如何求出点权和的平方以及点权的平方和,对于每个询问(x,y)
答案就是x到y的路径上的点权和的平方以及点权的平方和,用lca来做,
如果手贱,可以打树链剖分
#include <cmath>
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <queue>
const long long maxlongint=2147483647;
const long long mo=1000000007;
const long long N=200005;
using namespace std;
long long g[N][25],n,m,q,ans,last[N*4],next[N*4],to[N*4],tot,deep[N],d[N*2],dfn[N],low[N],dd;
long long f[N][25],f1[N][25],last1[N*4],next1[N*4],to1[N*4],belong[N],be,sum[N],k;
bool bz[N*4];
int bj(int x,int y)
{
next[++tot]=last[x];
last[x]=tot;
to[tot]=y;
}
int bj1(int x,int y)
{
next1[++tot]=last1[x];
last1[x]=tot;
to1[tot]=y;
}
int tarjan(int x)
{
dfn[x]=low[x]=++dd;
d[++tot]=x;
for(int i=last[x];i;i=next[i])
if(bz[i])
{
bz[i]=bz[i^1]=false;
int j=to[i];
if(!dfn[j])
{
tarjan(j);
low[x]=min(low[x],low[j]);
}
else
low[x]=min(low[x],low[j]);
}
if(dfn[x]==low[x])
{
be++;
while(low[d[tot]]>=dfn[x])
{
belong[d[tot--]]=be;
sum[be]++;
}
}
}
int dg(int x)
{
bz[x]=false;
for(int i=last1[x];i;i=next1[i])
{
if(bz[to1[i]])
{
deep[to1[i]]=deep[x]+1;
g[to1[i]][0]=x;
f[to1[i]][0]=sum[to1[i]];
f1[to1[i]][0]=sum[to1[i]]*sum[to1[i]];
dg(to1[i]);
}
}
}
int llca(int x,int y)
{
if(deep[x]>deep[y])
{
x=x^y;
y=x^y;
x=x^y;
}
for(int i=log2(n);i>=0;i--)
{
if(deep[g[y][i]]>=deep[x])
{
k+=f[y][i];
ans-=f1[y][i];
y=g[y][i];
}
}
for(int i=log2(n);i>=0;i--)
{
if(g[y][i]!=g[x][i])
{
k+=f[y][i]+f[x][i];
ans-=f1[y][i]+f1[x][i];
y=g[y][i];
x=g[x][i];
}
}
if(x!=y)
{
k+=f[x][0]+f[y][0];
ans-=f1[y][0]+f1[x][0];
return g[x][0];
}
else
return x;
}
int main()
{
scanf("%lld%lld%lld",&n,&m,&q);
tot=1;
for(int i=1;i<=m;i++)
{
int x,y;
scanf("%d%d",&x,&y);
bj(x,y);
bj(y,x);
}
memset(bz,true,sizeof(bz));
tot=0;
tarjan(1);
tot=0;
for(int x=1;x<=n;x++)
{
for(int i=last[x];i;i=next[i])
{
int j=to[i];
if(belong[x]!=belong[j])
{
bj1(belong[x],belong[j]);
bj1(belong[j],belong[x]);
}
}
}
f[1][0]=sum[1];
f1[1][0]=sum[1]*sum[1];
deep[1]=1;
memset(bz,true,sizeof(bz));
dg(1);
for(int i=1;i<=log2(n);i++)
for(int j=1;j<=n;j++)
{
g[j][i]=g[g[j][i-1]][i-1];
f[j][i]=f[j][i-1]+f[g[j][i-1]][i-1];
f1[j][i]=f1[j][i-1]+f1[g[j][i-1]][i-1];
}
ans=0;
for(int i=1;i<=q;i++)
{
int x1,y1;
scanf("%d%d",&x1,&y1);
k=0;
int lca=llca(belong[x1],belong[y1]);
k+=sum[lca];
ans-=sum[lca]*sum[lca];
ans+=k*k;
}
printf("%lld",ans);
}
【NOIP2016提高A组模拟9.15】Map的更多相关文章
- 【JZOJ4784】【NOIP2016提高A组模拟9.15】Map
题目描述 输入 输出 样例输入 4 4 2 1 2 2 3 3 2 3 4 1 2 1 4 样例输出 14 数据范围 样例解释 upd:保证原图连通. "不相交路径"的定义为不存在 ...
- NOIP2016提高A组模拟10.15总结
第一题,就是将原有的式子一步步简化,不过有点麻烦,搞了很久. 第二题,枚举上下边界,维护一个单调队列,二分. 比赛上没有想到,只打了个暴力,坑了80分. 第三题,贪心,最后的十多分钟才想到,没有打出来 ...
- 【NOIP2016提高A组模拟10.15】打膈膜
题目 分析 贪心, 先将怪物按生命值从小到大排序(显然按这个顺序打是最优的) 枚举可以发对少次群体攻击, 首先将所有的群体攻击发出去, 然后一个一个怪物打,当当前怪物生命值大于2,如果还有魔法值就放重 ...
- 【NOIP2016提高A组模拟10.15】最大化
题目 分析 枚举两个纵坐标i.j,接着表示枚举区域的上下边界, 设对于每个横坐标区域的前缀和和为\(s_l\),枚举k, 显然当\(s_k>s_l\)时,以(i,k)为左上角,(j,k)为右下角 ...
- 【NOIP2016提高A组模拟10.15】算循环
题目 分析 一步步删掉循环, 首先,原式是\[\sum_{i=1}^n\sum_{j=1}^m\sum_{k=i}^n\sum_{l=j}^m\sum_{p=i}^k\sum_{q=j}^l1\] 删 ...
- 【NOIP2016提高A组模拟9.15】Osu
题目 分析 考虑二分答案, 二分小数显然是不可取的,那么我们将所有可能的答案求出来,记录在一个数组上,排个序(C++调用函数很容易超时,手打快排,时间复杂度约为\(O(>8*10^7)\),但相 ...
- 【NOIP2016提高A组模拟9.15】Math
题目 分析 因为\((-1)^2=1\), 所以我们只用看\(\sum_{j=1}^md(i·j)\)的值模2的值就可以了. 易证,一个数x,只有当x是完全平方数时,d(x)才为奇数,否则为偶数. 那 ...
- 【NOIP2016提高A组模拟8.15】Garden
题目 分析 其实原题就是[cqoi2012][bzoj2669]局部极小值. 有一个n行m列的整数矩阵,其中1到nm之间的每个整数恰好出现一次.如果一个格子比所有相邻格子(相邻是指有公共边或公共顶点) ...
- 【NOIP2016提高A组模拟8.15】Throw
题目 分析 首先对于一个状态(a,b,c),假定a<=b<=c: 现在考虑一下这个状态,的转移方案: \[1,中间向两边跳(a,b,c)-->(a*2-b,a,c).(a,b,c)- ...
随机推荐
- centos7 忘记root密码,如何进入单用户模式。
init方法 1.centos7的grub2界面会有两个入口,正常系统入口和救援模式: 2.修改grub2引导 在正常系统入口上按下"e",会进入edit模式,搜寻ro那一行,以l ...
- 如何解决idea本身的乱码以及解决代码中出现的乱码?
1:解决idea中控制台的乱码现象(3中方法): 第一种: 如图需要找到idea的安装路径: idea\IntelliJ IDEA 2018.3.2\bin 在这个路径下面有一个文件叫:idea64. ...
- AGC035 A - XOR Circle【分析】
题目传送门 题意简述: (就是连环的意思) 唔,这道题考场上写了个什么神仙做法,数据太水了居然过了: // #include<cstdio> #include<algorithm&g ...
- dos2unix Linux解决编写脚本出现“%0D
## Linux解决编写脚本出现“%0D”# 安装# yum install -y dos2unix# 然后进行转化一下脚本,将其中的install_mysql.sh换成你的脚本# dos2unix ...
- ideal项目启动及问题
Error running 'xxx项目' Command line is too long(idea版) 错误] Error running ‘xxx项目’: Command line is too ...
- 【Linux 网络编程】端口
(1)众所周知的端口:0~1023,这些端口由IANA分配和控制它们紧密绑定用于一些服务.常用这些端口的通讯 明确表明了某些协议.例如:21端口为ftp服务端口. (2)注册端口:1024~49 ...
- [转帖]PostgreSQL pg_dump&psql 数据的备份与恢复
PostgreSQL pg_dump&psql 数据的备份与恢复 https://www.cnblogs.com/chjbbs/p/6480687.html 文章写的挺好 今天试了下 挺不 ...
- Ubuntu 19.04 下使用Remmina连接window服务器部署maven项目
先将打包好的war包上传到tomcat的webapps目录下 如果配置了tomcat的虚拟路径,那就放进虚拟路径的webapps文件李 修改tomcat安装目录下的conf/server.xml文件 ...
- C++中的new/delete、构造/析构函数、dynamic_cast分析
1,new 关键字和 malloc 函数区别(自己.功能.应用): 1,new 关键字是 C++ 的一部分: 1,如果是 C++ 编译器,则肯定可以用 new 申请堆空间内存: 2,malloc 是由 ...
- [.net core]11.异常页
.net core中的异常页很重要 因为可以查看异常的堆栈信息, 请求的参数(如果有),cookie, http头 帮助我们快速的定位问题 .net core web app 默认开启了异常页,但是 ...