P4592 [TJOI2018]异或

题意:

现在有一颗以 1 为根节点的由 n 个节点组成的树,节点从 1 至 n 编号。树上每个节点上都有一个权值 vi。现在有 q 次操作,操作如下:
1 x z:查询节点 x 的子树中的节点权值与 z 异或结果的最大值。
2 x y z:查询节点 x 到节点 y 的简单路径上的节点的权值与 z 异或结果最大值。

题解:

很明显的可持久化01Trie
对于第一个问题,直接按照时间戳(DFS序)建立点权的可持久化01Trie,每次查询就是对区间[dfn[u],dfn[u]+siz[u]-1]的询问,(u的所有儿子都被包含在这个区间内)
关于第二个问题,我们都知道对于u->v的路径,我们可以拆分成rt到u,rt到v,rt到lca,rt到fa[lca](老套路了)这四套路径,建立rt到所有点的可持久化01Trie,然后查询这四条路找到答案
相当于对于两问建了两个可持久化01Trie

代码:

#include<bits/stdc++.h>
#define debug(a,b) printf("%s = %d\n",a,b);
using namespace std;
typedef long long ll;
typedef pair<int, int> PII;
clock_t startTime, endTime;
//Fe~Jozky
const ll INF_ll=1e18;
const int INF_int=0x3f3f3f3f;
inline ll read(){ll s=0,w=1ll;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')w=-1ll;ch=getchar();}while(ch>='0'&&ch<='9') s=s*10ll+((ch-'0')*1ll),ch=getchar();//s=(s<<3)+(s<<1)+(ch^48);return s*w;
}
void rd_test(){#ifdef ONLINE_JUDGE#elsestartTime = clock(); //计时开始freopen("in.txt","r",stdin);#endif
}
void Time_test(){#ifdef ONLINE_JUDGE#elseendTime = clock(); //计时结束printf("\n运行时间为:%lfs\n",(double)(endTime - startTime) / CLOCKS_PER_SEC);#endif
}
int n,m,sum,dep[200001],a[200001],ktot,size[200001],tpos[200001],pre[200001],head[200001],tot,f[200001][25];
struct edge{int to,next;
}g[1000001];
inline void made(int from,int to){g[++tot].to=to;g[tot].next=head[from];head[from]=tot;
}
struct Trie{int n,son[10000001][2],cnt=1,sum,root[200001],ct[10000001];void ins(int &rt,int x,int T){ct[++cnt]=ct[rt]+1;son[cnt][0]=son[rt][0];son[cnt][1]=son[rt][1];rt=cnt;if (T==-1) return;register bool y=(x>>T)&1;ins(son[rt][y],x,T-1);}inline void insert(int pre,int rt,int x){root[rt]=root[pre];ins(root[rt],x,30);}int QUE(int i,int j,int x,int T){//序列版if (T==-1) return 0;register bool y=(x>>T)&1;if (ct[son[j][1^y]]>ct[son[i][1^y]]) return ((1<<T)+QUE(son[i][1^y],son[j][1^y],x,T-1));else return QUE(son[i][y],son[j][y],x,T-1);}int queryxx(int i,int j,int lca,int fa,int x,int T){//树上差分版if (T==-1) return 0;register bool y=(x>>T)&1;if (ct[son[j][1^y]]+ct[son[i][1^y]]>ct[son[lca][1^y]]+ct[son[fa][1^y]]) return ((1<<T)+queryxx(son[i][1^y],son[j][1^y],son[lca][1^y],son[fa][1^y],x,T-1));else return queryxx(son[i][y],son[j][y],son[lca][y],son[fa][y],x,T-1);}int queryx(int i,int j,int lc,int flc,int x,int T){return queryxx(root[i],root[j],root[lc],root[flc],x,T);}inline int query(int l,int r,int x){return QUE(root[l-1],root[r],x,30);}
}tr1,tr2;
void dfs0(int u,int fa){dep[u]=dep[fa]+1;f[u][0]=fa;tpos[u]=++ktot;pre[ktot]=u;tr1.insert(fa,u,a[u]);size[u]=1;for (int i=1;i<=21;i++) f[u][i]=f[f[u][i-1]][i-1];for (int i=head[u];i;i=g[i].next){int v=g[i].to;if (v==fa) continue;dfs0(v,u);size[u]+=size[v];}
}
inline int LCA(int x,int y){if (dep[x]<dep[y]) swap(x,y);for (int i=21;i>=0;i--){if (dep[f[x][i]]>=dep[y]) x=f[x][i];}if (x==y) return x;for (int i=21;i>=0;i--){if (f[x][i]!=f[y][i]) x=f[x][i],y=f[y][i];}return f[x][0];
}
int main(){rd_test();n=read();m=read();for (int i=1;i<=n;i++) a[i]=read();for (int i=1;i<n;i++){int x=read(),y=read();made(x,y);made(y,x);}dfs0(1,0);for (int i=1;i<=n;i++){tr2.insert(i-1,i,a[pre[i]]);}while (m--){int opt=read();if (opt==1){int x=read(),y=read();printf("%d\n",tr2.query(tpos[x],tpos[x]+size[x]-1,y));}else{int x=read(),y=read(),z=read();int lca=LCA(x,y);printf("%d\n",tr1.queryx(x,y,lca,f[lca][0],z,30));}}Time_test();
}

写的另一个还没改完的代码:

#include<bits/stdc++.h>
#define debug(a,b) printf("%s = %d\n",a,b);
using namespace std;
typedef long long ll;
typedef pair<int, int> PII;
//Fe~Jozky
clock_t startTime, endTime;
const ll INF_ll=1e18;
const int INF_int=0x3f3f3f3f;
inline ll read(){ll s=0,w=1ll;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')w=-1ll;ch=getchar();}while(ch>='0'&&ch<='9') s=s*10ll+((ch-'0')*1ll),ch=getchar();//s=(s<<3)+(s<<1)+(ch^48);return s*w;
}
void rd_test(){#ifdef ONLINE_JUDGE#elsestartTime = clock(); //计时开始freopen("in.txt","r",stdin);#endif
}
void Time_test(){#ifdef ONLINE_JUDGE#elseendTime = clock(); //计时结束printf("\n运行时间为:%lfs\n",(double)(endTime - startTime) / CLOCKS_PER_SEC);#endif
}
const int maxn=3e5+9;
vector<int>vec[maxn];
struct tree{int cnt=0;int ch[3];
}tr[maxn*40];
int rt[maxn];
int a[maxn];
int fa[maxn][25], dep[maxn], lg[maxn];
int rtnum=0;
int dfn[maxn],predfn[maxn];
int dfnnum=0;
int siz[maxn];
int newa[maxn];
void insert(int now,int pre,int x){for(int i=30;i>=0;i--){int c=((x>>i)&1);tr[now].ch[c^1]=tr[pre].ch[c^1];tr[now].ch[c]=++rtnum;now=tr[now].ch[c];pre=tr[pre].ch[c];tr[now].cnt=tr[pre].cnt+1;}
}
int query(int L,int R,int x){int sum=0;for(int i=30;i>=0;i--){int c=((x>>i)&1);if(tr[tr[R].ch[c^1]].cnt>tr[tr[L].ch[c^1]].cnt){sum+=(1<<i);L=tr[L].ch[c^1];R=tr[R].ch[c^1]; }else {L=tr[L].ch[c];R=tr[R].ch[c]; }}return sum;
}
void dfs(int now,int fath){siz[now]=1;dep[now]=dep[fath]+1;fa[now][0]=fath;for(int i=1;(1<<i)<=dep[now];i++)fa[now][i]=fa[fa[now][i-1]][i-1];dfn[now]=++dfnnum;newa[dfnnum]=a[now];//predfn[dfnnum]=now;for(int i=0;i<vec[now].size();i++){if(vec[now][i]!=fath){dfs(vec[now][i],now);siz[now]+=siz[vec[now][i]];}}
}
int LCA(int x,int y){if(dep[x]<dep[y])swap(x,y);while(dep[x]>dep[y])x=fa[x][lg[dep[x]]-dep[y]];if(x==y)return x;for(int i=lg[dep[x]];i>=0;i--){if(fa[x][i]!=fa[y][i]){x=fa[x][i];y=fa[y][i];}}return fa[x][0];
}
int main()
{rd_test(); int n,m;cin>>n>>m;for(int i=1;i<=n;i++)cin>>a[i];for(int i=1;i<n;i++){int u,v;cin>>u>>v;vec[u].push_back(v);vec[v].push_back(u);}lg[0]=-1;for(int i=1;i<=n;i++)lg[i]=lg[i>>1]+1;dfs(1,0);rt[0]=++rtnum;insert(rt[0],0,0);int tot=0;for(int i=1;i<=dfnnum;i++){tot^=newa[i];rt[i]=++rtnum;insert(rt[i],rt[i-1],tot);}for(int i=1;i<=m;i++){int op;scanf("%d",&op);int x,y,z;if(op==1){scanf("%d%d",&x,&z);int ans=query(rt[dfn[x]-1],rt[dfn[x]+siz[x]-1],z);printf("%d\n",ans);}else {scanf("%d%d%d",&x,&y,&z);if(dfn[x]>dfn[y])swap(x,y);int lca=LCA(x,y);//int ans=max(query(rt[dfn[lca]-1],rt[dfn[x]],z),query(rt[dfn[x]+siz[x]-1],rt[dfn[y]],z));cout<<"???"<<endl;}}Time_test();
}

P4592 [TJOI2018]异或相关推荐

  1. P4592 [TJOI2018]异或 (可持久化Trie)

    [题目链接] https://www.luogu.org/problemnew/show/P4592 题目描述 现在有一颗以\(1\)为根节点的由\(n\)个节点组成的树,树上每个节点上都有一个权值\ ...

  2. 【[TJOI2018]异或】

    写板子了,可持久化\(Trie\)的板子了 其实和主席树写法类似,还是存好左右儿子之后存好权值 之后差分去查询就好了 这道题第一问我们直接\(dfs\)序转化成区间 第二问搞成\(x,y,lca(x, ...

  3. 可持久化3--可持久化01Trie

    01Trie 可持久化 01Trie 的方式和可持久化值域线段树的方式是相似的,只是以 01字典树 的方式来维护值域.一般用来解决异或相关的能够按位贪心的题目. 其实就是将可持久化线段树中的操作嫁接到 ...

  4. java ftp输出流_java输出流实现文件下载

    //导出Excel try { HSSFWorkbook wb = carService.export(list); //调用service方法~! response.setContentType(& ...

  5. [学习笔记]可持久化数据结构——数组、并查集、平衡树、Trie树

    可持久化:支持查询历史版本和在历史版本上修改 可持久化数组 主席树做即可. [模板]可持久化数组(可持久化线段树/平衡树) 可持久化并查集 可持久化并查集 主席树做即可. 要按秩合并.(路径压缩每次建 ...

  6. 不占用多余空间实现值的交换——异或运算

    首先什么是异或运算? ^规则: 0 ^ x = x x ^ x = 0 那么 a 与 b 交换值如何做呢???三行代码

  7. 左神讲算法——异或的高级操作(两数交换+经典面试题)

    目录 1. 异或的性质 2. 两数交换 3. 经典面试例题 参考链接:2021最新左神数据结构算法全家桶 1. 异或的性质 异或可以看成相同为1,不同为0:也可以看作无进位相加,有奇数个1则结果为1, ...

  8. 《The Sixth Sense》(《灵异第六感》)观后

    记得在学校的时候看过一部片子<左眼看到鬼>,现在想想那部片子有抄袭<Tht Sixth Sense>的嫌疑.不过抄袭也差得远. 现在真的懒得看港台片了,国内的农村,山村题材的都 ...

  9. 计算机入门新人必学,异世修真人怎么玩?新手快速入门必备技巧

    异世修真人怎么快速入门?最近新出来的一款文字修仙游戏,很多萌新不知道怎么玩?进小编给大家带来了游戏新手快速入门技巧攻略,希望可以帮到大家. 新手快速入门攻略 1.开局出来往下找婆婆,交互给点钱,旁边有 ...

最新文章

  1. ubuntu server 改变系统语言支持中文
  2. python手机app 授权登录_Appium+unittest+python登录app
  3. 启明云端分享|ESP32-C3模块入门应用
  4. MTD和 uboot中的bootargs 下属 mtdparts
  5. from torchcrf import CRF
  6. php试题与答案(二),php面试题附答案二
  7. 解析超大文件_MySQL物理文件结构和SQL执行流程
  8. HDU.1002 A + B Problem II
  9. 解决矩池云使用中ssh链接的时候日志丢失
  10. win7 蓝牙4.0 ble驱动_Android FrameWorkamp;HAL视频最新进度: 蓝牙更新6节(更新时间2019年3月27日)...
  11. Jmeter测试脚本编写详解(配详图)
  12. 办公室计算机打印机共享,办公室共享连接打印机全攻略,办公人必会操作技能...
  13. H.264 NAL语法语意以及字节流的语法语意
  14. 树莓派3B+ 智能家居(HomeKit)
  15. veracrypt 创建文件型加密卷
  16. 用python赚零花钱_买不起猪肉了?用Python炒股赚点零花钱吧
  17. 获取SVG文件中use标签xlink:href的值
  18. word表格分开快捷键_Word拆分与合并单元格快捷键
  19. react组件的render方法
  20. MotionEvent 事件解读

热门文章

  1. 三年磨一剑,五次被拒稿,交大博士坚持稿件申诉,终发表学科顶刊
  2. 这些高校竟因名字太“坑爹”被误会为三本?盘点九所实力强劲但被名字耽误的大学...
  3. 马斯克和贝索斯的“星球大战”
  4. php psr 编码规范_PHP之PSR-4规范:自动加载
  5. abp框架java,【Net】ABP框架学习之正面硬钢
  6. 怎么让图片手机上排列_荣耀手机系列档次怎么排列?
  7. ofdm解调算法_OFDM系统中固定频偏算法
  8. python tuple args_Python基本数据类型之tuple
  9. activity 防止多次打开_Android开发Activity任务和返回栈
  10. python base64编码_JS和Python实现AES算法