BZOJ_5338_ [TJOI2018]xor_可持久化trie

Description

有一棵点数为N的树,树边有边权。给你一个在0~N之内的正整数K,你要在这棵树中选择K个点,将其染成黑色,并
将其他的N-K个点染成白色。将所有点染色后,你会获得黑点两两之间的距离加上白点两两之间距离的和的收益。
问收益最大值是多少。

Input

第一行两个整数N,K。
接下来N-1行每行三个正整数fr,to,dis,表示该树中存在一条长度为dis的边(fr,to)。
输入保证所有点之间是联通的。
N<=2000,0<=K<=N

Output

输出一个正整数,表示收益的最大值。

Sample Input

5 2
1 2 3
1 5 1
2 3 1
2 4 2

Sample Output

17
【样例解释】
将点1,2染黑就能获得最大收益。

HINT

2017.9.12新加数据一组 By GXZlegend


博客里没有几道可持久化trie的题,还是更一篇吧。

同时要求子树和两点路径上的信息,

只能用两个序维护一下,然后可持久化一下随便搞搞。

代码:

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cstdlib>
using namespace std;
#define N 200050
int head[N],to[N],nxt[N],val[N],cnt,n,m,be[N],ed[N],tot,root[N],t[N*33],sanae,ch[N*33][2],son[N],siz[N],fa[N],dep[N],top[N];
int t2[N*33],ch2[N*33][2],dfn[N],marisa,reimu,root2[N];
inline void add(int u,int v) {
to[++cnt]=v; nxt[cnt]=head[u]; head[u]=cnt;
}
void update(int x,int c,int &y,int q) {
y=++sanae; int p=y; t[p]=t[q]+c;
int i;
for(i=30;i>=0;i--) {
int k=(x>>i)&1;
ch[p][k]=++sanae; ch[p][!k]=ch[q][!k];
p=ch[p][k]; q=ch[q][k]; t[p]=t[q]+c;
}
}
void upd(int x,int c,int &y,int q) {
y=++reimu; int p=y; t2[p]=t2[q]+c;
// printf("upd---%d %d %d %d\n",p,q,t2[p],t2[q]);
int i;
for(i=30;i>=0;i--) {
int k=(x>>i)&1;
ch2[p][k]=++reimu; ch2[p][!k]=ch2[q][!k];
p=ch2[p][k]; q=ch2[q][k]; t2[p]=t2[q]+c;
}
}
void dfs(int x,int y) {
dfn[x]=++marisa; upd(val[x],1,root2[marisa],root2[marisa-1]);
// printf("dfs---%d %d %d %d\n",root2[marisa],root2[marisa-1],t2[root2[marisa]],t2[root2[marisa-1]]);
// printf("%d %d %d %d\n",t2[root2[1]],t2[root2[2]],t2[root2[3]],t2[root2[4]]);
int i; be[x]=++tot; update(val[x],1,root[tot],root[tot-1]); siz[x]=1; fa[x]=y; dep[x]=dep[y]+1;
for(i=head[x];i;i=nxt[i]) {
if(to[i]!=y) {
dfs(to[i],x); siz[x]+=siz[to[i]]; if(siz[son[x]]<siz[to[i]]) son[x]=to[i];
}
}
ed[x]=++tot; update(val[x],-1,root[tot],root[tot-1]);
}
void dfs2(int x,int t) {
top[x]=t;
if(son[x]) dfs2(son[x],t);
int i;
for(i=head[x];i;i=nxt[i])if(to[i]!=fa[x]&&to[i]!=son[x]) dfs2(to[i],to[i]);
}
int lca(int x,int y) {
while(top[x]!=top[y]) {
if(dep[top[x]]>dep[top[y]]) swap(x,y);
y=fa[top[y]];
}
return dep[x]<dep[y]?x:y;
}
int solve1(int x,int y,int v) {
// printf("%d %d %d %d\n",x,y,t2[x],t2[y]);
int i,re=0;
for(i=30;i>=0;i--) {
int k=!((v>>i)&1);
if(t2[ch2[y][k]]-t2[ch2[x][k]]) {
re+=(1<<i); x=ch2[x][k]; y=ch2[y][k];
}else x=ch2[x][!k],y=ch2[y][!k];
}
return re;
}
int solve2(int x,int y,int z,int w,int v) {
int i,re=0;
for(i=30;i>=0;i--) {
int k=!((v>>i)&1);
if(t[ch[x][k]]+t[ch[y][k]]-t[ch[z][k]]-t[ch[w][k]]>0) re+=(1<<i),x=ch[x][k],y=ch[y][k],z=ch[z][k],w=ch[w][k];
else x=ch[x][!k],y=ch[y][!k],z=ch[z][!k],w=ch[w][!k];
}
return re;
}
int main() {
scanf("%d%d",&n,&m);
int i,x,y,opt,z;
for(i=1;i<=n;i++) scanf("%d",&val[i]);
for(i=1;i<n;i++) scanf("%d%d",&x,&y),add(x,y),add(y,x);
dfs(1,0); dfs2(1,1);
// printf("%d %d %d %d\n",t2[root2[1]],t2[root2[2]],t2[root2[3]],t2[root2[4]]);
for(i=1;i<=m;i++) {
scanf("%d%d%d",&opt,&x,&y);
if(opt==1) {
// printf("%d\n",root2[dfn[x]-1]);
printf("%d\n",solve1(root2[dfn[x]-1],root2[dfn[x]+siz[x]-1],y));
}else {
scanf("%d",&z);
int l=lca(x,y);
printf("%d\n",solve2(root[be[x]],root[be[y]],root[be[l]],root[be[fa[l]]],z));
}
}
}

BZOJ_5338_ [TJOI2018]xor_可持久化trie的更多相关文章

  1. BZOJ.5338.[TJOI2018]xor(可持久化Trie)

    BZOJ LOJ 洛谷 惊了,18年了还有省选出模板题吗= = 做这题就是练模板的,我就知道我忘的差不多了 询问一就用以DFS序为前缀得到的可持久化Trie做,询问二很经典的树上差分. 注意求询问二的 ...

  2. [BZOJ5338][TJOI2018]xor(可持久化Trie)

    可持久化Trie模板题. 建两种可持久化Trie,每个点两棵,一棵对DFS求前缀和,一棵对祖先求前缀和. 或者树剖,不好写多少还多个log. #include<cstdio> #inclu ...

  3. BZOJ 5338: [TJOI2018]xor 可持久化trie+dfs序

    强行把序列问题放树上,好无聊啊~ code: #include <bits/stdc++.h> #define N 200005 #define setIO(s) freopen(s&qu ...

  4. BZOJ5338 [TJOI2018] Xor 【可持久化Trie树】【dfs序】

    题目分析: 很无聊的一道题目.首先区间内单点对应异或值的询问容易想到trie树.由于题目在树上进行,case1将路径分成两段,然后dfs的时候顺便可持久化trie树做询问.case2维护dfs序,对d ...

  5. 可持久化trie(BZOJ5338: [TJOI2018]xor)

    题面 BZOJ Sol 显然是要维护一个区域的 \(trie\) 树,然后贪心 区间 \(trie\) 树??? 可持久化 \(trie\) 树??? 直接参考主席树表示出区间的方法建立 \(trie ...

  6. 洛谷P4592 [TJOI2018]异或 【可持久化trie树】

    题目链接 BZOJ4592 题解 可持久化trie树裸题 写完就A了 #include<algorithm> #include<iostream> #include<cs ...

  7. [TJOI2018] Xor 异或 (可持久化Trie,树链剖分)

    题目描述 现在有一颗以 1 为根节点的由 n 个节点组成的树,树上每个节点上都有一个权值 \(v_i\).现在有 Q 次操作,操作如下: 1 x y :查询节点 x 的子树中与 y 异或结果的最大值. ...

  8. HDU 4757 Tree(可持久化Trie+Tarjan离线LCA)

    Tree Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 102400/102400 K (Java/Others) Total Su ...

  9. 【BZOJ4260】 Codechef REBXOR 可持久化Trie

    看到异或就去想前缀和(⊙o⊙) 这个就是正反做一遍最大异或和更新答案 最大异或就是很经典的可持久化Trie,从高到低贪心 WA: val&(1<<(base-1))得到的并不直接是 ...

随机推荐

  1. zoj 2949 - Coins of Luck

    题目:有2中面条各n碗.每次抛硬币推断吃哪一种(到一种吃完为止).问抛硬币的数学期望. 分析:动态规划.概率dp.求出每种结束状态(即,有一种吃完)的概率,分别乘以步长即为期望. 大黄解法:状态位剩余 ...

  2. 时钟展频技术能有效降低EMI,深入讲解展频发生器!

    原文地址:https://baijiahao.baidu.com/s?id=1608649367453023659&wfr=spider&for=pc 相关文章: 1.http://b ...

  3. Java 获取本地IP地址

    private static String getIpAddress( ){ String ip = ""; Collection<InetAddress> colIn ...

  4. EasyPlayerPro windows播放器本地配置文件配置方法介绍

    需求背景 应EasyPlayerPro某客户需求,在EasyPlayerPro启动时,自动播放指定的url源, 不需要每次都去手动填写, 且实现自动播放,不需要手动的单击播放按钮: 为响应该需求,特增 ...

  5. 基于传统IPC基础上的RTMP互联网推流摄像机方案设计

    在我之前的一篇博客<EasyRTMP内置进入摄像机中实现网络推流直播摄像机的功能>中,我阐述了一种将RTMP推流内置到摄像机系统内部,实现安防摄像机转互联网直播的RTMP推流摄像机功能,如 ...

  6. C#根据Type获取默认值

    简单的获取某变量类型的默认值 在c#中为我们提供了default(),但是default的参数是具体的类名, 如何根据变量类型的Type获取默认值Code如下: 1 public static obj ...

  7. 九度OJ 1165:字符串匹配 (模式匹配)

    时间限制:1 秒 内存限制:32 兆 特殊判题:否 提交:3219 解决:1149 题目描述: 读入数据string[ ],然后读入一个短字符串.要求查找string[ ]中和短字符串的所有匹配,输出 ...

  8. python数据分析之:绘图和可视化

    在数据分析领域,最出名的绘图工具就是matlib.在Python同样有类似的功能.就是matplotlib.前面几章我们都在介绍数据的生成,整理,存储.那么这一章将介绍如果图形化的呈现这些数据.来看下 ...

  9. linux c编程:gdb的使用

    首先用一个简单的打印字符的程序来做下示例 #include<stdio.h>#include<string.h>void main(){    int i=0;    char ...

  10. spring运行步骤

    Spring确实使你能通过最简单可行的解决的方法来解决你的问题. 而这是有有非常大价值的.同一时候他的源码的设计理念也受到非常多程序猿的追捧,简洁,易用.但是从哪着手研究Spring却是非常多新手头疼 ...