【JZOJ5363】【NOIP2017提高A组模拟9.14】生命之树 Trie+启发式合并
题面


45
在比赛中,我只想到了45分的暴力。
对于一个树中点对,相当于在他们的LCA及其祖先加上这个点对的贡献。
那么这个可以用dfs序+树状数组来维护。
100
想法
我想到了可能要用trie树来维护这个字符串的公共前缀。
然后这就面临了两个很严重的问题。
1.我对于每个子树都要建一个trie,所以这是\(O(n^2)\)的复杂度。
我想到了要合并儿子的信息,但是这个合并似乎是无法存储。
2.我还要处理xor的问题,我的想法是在trie上的每个结点上维护一个蜜汁容器。
可能这要用到xor的某些运算法则,但我并不知道如何实现。
然后正解就恰好解决了我这两个问题。
zrO lhy Orz
1.trie数可以使用启发式合并,那么时间复杂度就降为\(O(nlogn)\)。
合并的时候,可以抛弃掉子树的信息,所以空间复杂度不会超过\(O(n)\)。
2.xor我们考虑按位分治,那么我们给trie上的每个结点维护一个\(cnt[i][j][0/1]\)。
表示这个结点\(i\)为根的子树内,有多少个数的二进制下第\(j\)位为\(0/1\)的个数。
这个在trie合并时可以简单合并。同时在合并的时候就能利用这个\(cnt\)统计答案。
具体就不展开,也就是\(cnt(*)(*)[0]*cnt(*)(*)[1]\)之类的。
Code
#include<bits/stdc++.h>
#define ll long long
#define fo(i,x,y) for(int i=x;i<=y;i++)
#define fd(i,x,y) for(int i=x;i>=y;i--)
#define ln(x,y) int(log(x)/log(y))
using namespace std;
const char* fin="1.in";
const char* fout="1.out";
const int inf=0x7fffffff;
int read(){
int x=0;
char ch=getchar();
while (ch<'0' || ch>'9') ch=getchar();
while (ch>='0' && ch<='9') x=x*10+ch-'0',ch=getchar();
return x;
}
const int maxn=100007,maxm=maxn*2,maxt=600007;
int fi[maxn],la[maxm],ne[maxm],tot;
void add_line(int a,int b){
tot++;
ne[tot]=fi[a];
la[tot]=b;
fi[a]=tot;
}
void add(int a,int b){add_line(a,b);add_line(b,a);}
int n,a[maxn],rt[maxn],si[maxn],num;
ll ans[maxn];
struct node{
int ne[26],cnt[17][2],cn[17][2];
}ac[maxt];
int b[maxn][2],hd,tl;
void dfs(int p,int _p,int de,ll &z){
fo(i,0,25){
int x=ac[p].ne[i],y=ac[_p].ne[i];
if (x){
fo(j,0,16) z+=1ll*ac[x].cnt[j][0]*(ac[_p].cnt[j][1]-ac[y].cnt[j][1])*(1<<j)*de,z+=1ll*ac[x].cnt[j][1]*(ac[_p].cnt[j][0]-ac[y].cnt[j][0])*(1<<j)*de;
if (y) dfs(x,y,de+1,z);
}
}
fo(j,0,16) z+=1ll*ac[p].cn[j][0]*ac[_p].cnt[j][1]*de*(1<<j),z+=1ll*ac[p].cn[j][1]*ac[_p].cnt[j][0]*de*(1<<j);
}
void link(int p,int _p){
fo(i,0,16){
ac[p].cn[i][0]+=ac[_p].cn[i][0];
ac[p].cn[i][1]+=ac[_p].cn[i][1];
ac[p].cnt[i][0]=ac[p].cn[i][0];
ac[p].cnt[i][1]=ac[p].cn[i][1];
}
fo(i,0,25){
int x=ac[p].ne[i],y=ac[_p].ne[i];
if (x && y) link(x,y);
else if (y) ac[p].ne[i]=y;
if (ac[p].ne[i]){
int x=ac[p].ne[i];
fo(i,0,16){
ac[p].cnt[i][0]+=ac[x].cnt[i][0];
ac[p].cnt[i][1]+=ac[x].cnt[i][1];
}
}
}
}
void merge(int x,int y,ll &z){
dfs(rt[x],rt[y],0,z);
link(rt[x],rt[y]);
si[x]+=si[y];
}
int main(){
freopen(fin,"r",stdin);
freopen(fout,"w",stdout);
scanf("%d",&n);
fo(i,1,n) scanf("%d",&a[i]);
fo(i,1,n){
char ch=getchar();
while (ch<'a' || ch>'z') ch=getchar();
rt[i]=++num;
int x=rt[i];
while (ch>='a' && ch<='z'){
fo(k,0,16) ac[x].cnt[k][a[i]>>k&1]++;
int y=ch-'a';
si[i]++;
x=ac[x].ne[y]=++num;
ch=getchar();
}
fo(k,0,16) ac[x].cnt[k][a[i]>>k&1]++,ac[x].cn[k][a[i]>>k&1]++;
}
fo(i,1,n-1) add(read(),read());
hd=tl=0;
b[++tl][0]=1;
while (hd++<tl){
int v=b[hd][0],from=b[hd][1];
for(int k=fi[v];k;k=ne[k])
if (la[k]!=from) b[++tl][0]=la[k],b[tl][1]=v;
}
fd(i,tl,1){
int v=b[i][0],from=b[i][1];
int mx=v;
for(int k=fi[v];k;k=ne[k])
if (la[k]!=from){
ans[v]+=ans[la[k]];
if (!mx || si[mx]<si[la[k]]) mx=la[k];
}
if (mx!=v) merge(mx,v,ans[v]);
for(int k=fi[v];k;k=ne[k])
if (la[k]!=from && la[k]!=mx){
merge(mx,la[k],ans[v]);
}
rt[v]=rt[mx];
}
fo(i,1,n) printf("%lld\n",ans[i]);
return 0;
}
【JZOJ5363】【NOIP2017提高A组模拟9.14】生命之树 Trie+启发式合并的更多相关文章
- JZOJ 【NOIP2017提高A组模拟9.14】捕老鼠
JZOJ [NOIP2017提高A组模拟9.14]捕老鼠 题目 Description 为了加快社会主义现代化,建设新农村,农夫约(Farmer Jo)决定给农庄里的仓库灭灭鼠.于是,猫被农夫约派去捕 ...
- [JZOJ]100047. 【NOIP2017提高A组模拟7.14】基因变异
21 世纪是生物学的世纪,以遗传与进化为代表的现代生物理论越来越多的 进入了我们的视野. 如同大家所熟知的,基因是遗传因子,它记录了生命的基本构造和性能. 因此生物进化与基因的变异息息相关,考察基因变 ...
- [JZOJ100047] 【NOIP2017提高A组模拟7.14】基因变异
Description 21 世纪是生物学的世纪,以遗传与进化为代表的现代生物理论越来越多的 进入了我们的视野. 如同大家所熟知的,基因是遗传因子,它记录了生命的基本构造和性能. 因此生物进化与基因的 ...
- [JZOJ]100046【NOIP2017提高A组模拟7.14】收集卡片
Star 计划订购一本将要发行的周刊杂志,但他可不是为了读书,而是-- 集卡. 已知杂志将要发行 N 周(也就是 N 期),每期都会附赠一张卡片.Star 通 过种种途径,了解到 N 期杂志附赠的卡片 ...
- JZOJ100048 【NOIP2017提高A组模拟7.14】紧急撤离
题目 题目大意 给你一个01矩阵,每次询问从一个点是否可以走到另一个点. 每次走只能往右或者往下. 思考历程 这题啊,我想的时候真的是脑洞大开-- 首先,我一眼看下去,既然要询问是否联通,那么能不能求 ...
- JZOJ 100029. 【NOIP2017提高A组模拟7.8】陪审团
100029. [NOIP2017提高A组模拟7.8]陪审团 Time Limits: 1000 ms Memory Limits: 131072 KB Detailed Limits Got ...
- JZOJ 5328. 【NOIP2017提高A组模拟8.22】世界线
5328. [NOIP2017提高A组模拟8.22]世界线 (File IO): input:worldline.in output:worldline.out Time Limits: 1500 m ...
- JZOJ 5329. 【NOIP2017提高A组模拟8.22】时间机器
5329. [NOIP2017提高A组模拟8.22]时间机器 (File IO): input:machine.in output:machine.out Time Limits: 2000 ms M ...
- JZOJ 5307. 【NOIP2017提高A组模拟8.18】偷窃 (Standard IO)
5307. [NOIP2017提高A组模拟8.18]偷窃 (Standard IO) Time Limits: 1000 ms Memory Limits: 262144 KB Description ...
随机推荐
- day1-初识Python以及环境搭建
---恢复内容开始--- 为什么学习Python? 软件质量:python的可读性很强,易于理解,非常接近于人类的自然语言. 提高开发者效率:相当于C,C++和JAVA等编译/静态型语言,Python ...
- 「BZOJ2300」[HAOI2011] 防线修建
传送门 操作离线之后倒着做,只有加点操作. 用set动态维护凸包即可. //Achen #include<algorithm> #include<iostream> #incl ...
- RabbitMQ代码操作之发消息和序列化机制
几个自动配置类: 1.RabbitAutoConfiguration2.有自动配置了连接工厂 ConnectionFactory3.RabbitProperties 封装了RabbitMQ的配置4.R ...
- js 数据绑定
// 回流:(重排 reflow) 当HTML的DOM结构(删除.增加.位置等)发生改变时引起DOM回流.浏览器重新计算DOM结构,重新的对当前DOM结构进行渲染 // 重绘:某一个元素的部分 ...
- lvs + keepalived + nginx + tomcat高可用负载反向代理服务器配置(一) 简介
一. 为什么这样构架 1. 系统高可用性 2. 系统可扩展性 3. 负载均衡能力 LVS+keepalived能很好的实现以上的要求,keepalived提供健康检查,故障转移,提高系统的可用性!采用 ...
- 容器安全与EDR的异同
以Docker为代表的容器技术,直接运行于宿主机操作系统内核,因此对于容器安全,很多人会有着这样的疑问:EDR(Endpoint Detection and Response)等主机安全方案,能否直接 ...
- Windows进程创建的流程分析
. 创建进程的大体流程: 创建进程的过程就是构建一个环境,这个环境包含了很多的机制 (比如自我保护, 与外界通信等等). 构建这个环境需要两种"人"来协调完成(用户态和内核 ...
- Xcode导航栏功能简介
1.Xcode 1.1.AboutXcode 1.2.Preferences General Accounts Behaviors1 Behavior2 Navigation Fonts& ...
- Python PIL 怎么知道写入图片格式的kb大小
把图片数据写入一个IO,读这个IO的长度大小: #-*-coding:utf-8-*- from PIL import Image import io img = Image.open("1 ...
- Leetcode949. Largest Time for Given Digits给定数字能组成最大的时间
给定一个由 4 位数字组成的数组,返回可以设置的符合 24 小时制的最大时间. 最小的 24 小时制时间是 00:00,而最大的是 23:59.从 00:00 (午夜)开始算起,过得越久,时间越大. ...