题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4298

题面:

  给定d张无向图,每张图都有n个点。一开始,在任何一张图中都没有任何边。接下来有m次操作,每次操作会给出a,b,k,意为在第k张图中的点a和点b之间添加一条无向边。你需要在每次操作之后输出有序数对(a,b)的个数,使得1<=a,b<=n,且a点和b点在d张图中都连通。

  第一行包含三个正整数d,n,m(1<=d<=200,1<=n<=5000,1<=m<=1000000),依次表示图的个数,点的个数和操作的个数。
  接下来m行,每行包含三个正整数a,b,k(1<=a,b<=n,1<=k<=d),依次描述每一个操作。
  输出m行m个正整数,依次表示每次操作之后满足条件的有序数对(a,b)的个数。

与连通性有关,那么就是并查集咯。

但在一个图里连通了两个点集之后,难道要遍历该点集所有点对,看看在其他图里是否连通?

1.启发式合并。那么对答案的影响,可以考虑落在 “新加入该点集” 的那些点上。

2.考虑 “与一个点在 d 张图里都连通的点的个数” 。

  连通意味着处在同一个连通块中。那么记录每个点在 d 张图中分别属于哪些连通块,这形成一个字符串。

  哈希记录某个字符串对应的点数即可。

需要用哈希表,而且消失的哈希值要从哈希表里删除,才能不超时。即使这样,自己还是平均时间的两倍。

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<map>
#define ll long long
#define ull unsigned long long
#define pb push_back
using namespace std;
int rdn()
{
int ret=;bool fx=;char ch=getchar();
while(ch>''||ch<''){if(ch=='-')fx=;ch=getchar();}
while(ch>=''&&ch<='')ret=ret*+ch-'',ch=getchar();
return fx?ret:-ret;
}
int g[];
void wrt(ll x)
{
if(!x){puts("");return;}
int t=;
while(x)g[++t]=x%,x/=;
for(int i=t;i;i--)putchar(g[i]+'');puts("");
}
const int N=,M=,bs=,M2=N*M*;
int n,m,D,fa[N][M],siz[N][M],ct[M2];
ll ans; ull bin[M],hs[N];
vector<int> vt[N][M];
namespace H{
const int md=3e7;
int hd[md],xnt,nxt[M2]; ull to[M2];
int get(ull x)
{
int h=x%md;
for(int i=hd[h];i;i=nxt[i])
if(to[i]==x)return i;
to[++xnt]=x; nxt[xnt]=hd[h]; hd[h]=xnt;
return xnt;
}
void del(ull x)
{
int h=x%md;
if(to[hd[h]]==x){hd[h]=nxt[hd[h]];return;}
for(int i=hd[h],lst=;i;lst=i,i=nxt[i])
if(to[i]==x){nxt[lst]=nxt[i];break;}
}
}
int main()
{
D=rdn();n=rdn();m=rdn();
bin[]=;for(int i=;i<=D;i++)bin[i]=bin[i-]*bs;
for(int i=;i<=n;i++)
{
for(int j=;j<=D;j++)
{
fa[i][j]=i; siz[i][j]=;
vt[i][j].pb(i); hs[i]+=i*bin[j];
}
ct[H::get(hs[i])]++;
}
ans=n;
for(int i=,u,v,d;i<=m;i++)
{
u=rdn();v=rdn();d=rdn();
u=fa[u][d]; v=fa[v][d];
if(u==v){wrt(ans);continue;}
if(siz[u][d]<siz[v][d])swap(u,v);
int tot=siz[u][d];
siz[u][d]+=siz[v][d]; vt[u][d].resize(siz[u][d]);
ull tmp=(u-v)*bin[d];
for(int j=,cr;j<siz[v][d];j++)
{
cr=vt[v][d][j]; fa[cr][d]=u; vt[u][d][tot++]=cr;
ull x=hs[cr],y=hs[cr]+tmp; hs[cr]+=tmp;
int t0=H::get(x),t1=H::get(y);
ct[t0]--; ans-=ct[t0]*; ans+=ct[t1]*; ct[t1]++;
}
vector<int> ().swap(vt[v][d]);
wrt(ans);
}
return ;
}

bzoj 4298 [ONTAK2015]Bajtocja——哈希+启发式合并的更多相关文章

  1. BZOJ.4298.[ONTAK2015]Bajtocja(Hash 启发式合并)

    题目链接 \(Description\) 给定\(d\)张无向图,每张图都有\(n\)个点.一开始,在任何一张图中都没有任何边. 接下来有\(m\)次操作,每次操作会给出\(a,b,k\),意为在第\ ...

  2. @bzoj - 4298@ [ONTAK2015]Bajtocja

    目录 @description@ @solution@ @accepted code@ @details@ @description@ 给定d张无向图,每张图都有n个点.一开始,在任何一张图中都没有任 ...

  3. BZOJ 2733: [HNOI2012]永无乡 启发式合并treap

    2733: [HNOI2012]永无乡 Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://www.lydsy.com/JudgeOnline/pr ...

  4. BZOJ 1483: [HNOI2009]梦幻布丁( 链表 + 启发式合并 )

    把相同颜色的串成一个链表, 然后每次A操作就启发式合并, 然后计算对答案的影响. ----------------------------------------------------------- ...

  5. BZOJ 3123: [Sdoi2013]森林 [主席树启发式合并]

    3123: [Sdoi2013]森林 题意:一个森林,加边,询问路径上k小值.保证任意时刻是森林 LCT没法搞,树上kth肯定要用树上主席树 加边?启发式合并就好了,小的树dfs重建一下 注意 测试点 ...

  6. bzoj 1483: [HNOI2009]梦幻布丁 (链表启发式合并)

    Description N个布丁摆成一行,进行M次操作.每次将某个颜色的布丁全部变成另一种颜色的,然后再询问当前一共有多少段颜色. 例如颜色分别为1,2,2,1的四个布丁一共有3段颜色. Input ...

  7. BZOJ 2733 [HNOI2012]永无乡 - 启发式合并主席树

    Description 1: 查询一个集合内的K大值 2: 合并两个集合 Solution 启发式合并主席树板子 Code #include<cstdio> #include<cst ...

  8. bzoj 2809 左偏树\平衡树启发式合并

    首先我们对于一颗树,要选取最多的节点使得代价和不超过m,那么我们可以对于每一个节点维护一个平衡树,平衡树维护代价以及代价的和,那么我们可以在logn的时间内求出这个子树最多选取的节点数,然后对于一个节 ...

  9. BZOJ 4919: [Lydsy1706月赛]大根堆 启发式合并

    我不会告诉你这是线段树合并的好题的... 好吧我们可以搞一个multiset在dfs时求出LIS(自带二分+排序)进行启发式合并,轻松加愉悦... #include<cstdio> #in ...

随机推荐

  1. java保留2位或n位小数

    1.直接使用字符串处理 double ds = Double.valueOf(String.format("%.3f", Math.random()).toString()); 这 ...

  2. [Python3] 003 变量类型概述 & 数字类型详叙

    目录 0. 变量类型概述 1. 数字类型详叙 1.1 整数 1.1.1 常用进制 1.1.2 少废话,上例子 1.2 浮点数 1.2.1 使用浮点数时可以"偷懒" 1.2.2 科学 ...

  3. Java 向上造型详解

    子类的对象可以向上造型为父类的类型.即父类引用子类对象,这种方式被称为向上造型. 在日常生活中,我们都扮演着不一样的角色.我们有可能是老师,有可能是学生,有可能是……, 但是我们都有共同的属性,例如: ...

  4. 如何去完成一个html网页

    其实我也是菜鸟一个,不过我还是想说说,昨晚看的视频好回忆回忆. 看到这样一个网页我们要怎么入手,这个就要像庖丁解牛一样,我们要对它的各个位置都要了解,分析出页面的结构,要有一个总体的把握,先把这个页面 ...

  5. You-Get,多网站视频下载工具,非常方便

    You-Get是一个非常优秀的网站视频下载工具.使用You-Get可以很轻松的下载到网络上的视频.图片及音乐. 按Win+R键打开运行,输入cmd,再输入命令 pip install you-get, ...

  6. Jmeter学习总结

    学习内容: 1.用户定义的变量 作用:多个地方使用同一个值,且该值在不同的环境下不同,方便脚本在不同环境下运行时修改. 2.基本的HTTP请求,请求方式:get 3.传入参数为json 4.HTTP信 ...

  7. luogu P1224 [NOI2013]向量内积

    传送门 挺有意思的一道题 暴力60就是枚举每个向量暴力check,随机选向量就能多骗一些分 然后两个向量内积要模\(k\)为\(0\),那么如果全部不为\(0\)就不合法.先考虑\(k=2\),对于向 ...

  8. SpringBoot_04springDataJPA

    说明:底层使用Hibernate 一.springDataJPA和mybatisPlus的使用区别 第一步: 把mybatisPlus的依赖.配置删除 包括:实体类的注解.引导类的mapperScan ...

  9. [译]送给 ES6 开发者的7个 hack

    关注原来的 JavaScript hacks,上面有一些新的好东西.2018 使用 JavaScript 写代码真的又变得有意思了! Hack #1 — 交换变量 使用数组结构来交换值 let a = ...

  10. Python 循环异或对文件进行加解密

    # -* -coding: UTF-8 -* - # 功能:异或方式对文件进行加密和解密 import os import datetime # 主函数 def main(): getInput() ...