HDU5274.Dylans loves tree
来源:互联网 发布:淘宝大药房是正品吗 编辑:程序博客网 时间:2024/05/16 14:35
/*题目里有一个很神奇的性质:路径上最多只有一个数出现奇数次。这应该马上想到异或。因为异或两次和没异或是等价的。此外异或满足区间减性质。因为有修改,我们很自然地想到用数据结构维护。最无脑的就是直接上树链剖分或是Splay维护区间xor值即可。仔细想一想,发现可以利用LCA消去“树上路径”,转化为根到x路径上求xor值。我们可以很经典地直接使用线段树或树状数组维护dfs序。有一个很强的trick就是权值可以为0!所以比如路径上有3个0,虽然他们xor值还是0,但是他们是出现了奇数次。我特意把A[i]说成∈自然数集而不是[0,100000],就是想尽量不被发现。怎么避免呢?单独维护0的情况?有一个很简单的解决方案:直接把读入时所有权值+1,输出的时候再-1即可!时间复杂度为O(N*log(N)^{2})或者O(N*log(N))O(N∗log(N))*/#pragma comment(linker, "/STACK:1024000000,1024000000")#include <map>#include <set>#include <stack>#include <queue>#include <cmath>#include <ctime>#include <vector>#include <cstdio>#include <cctype>#include <cstring>#include <cstdlib>#include <iostream>#include <algorithm>using namespace std;#define INF 0x3f3f3f3f#define inf -0x3f3f3f3f#define lson l,m,rt<<1#define rson m+1,r,rt<<1|1#define mem0(a) memset(a,0,sizeof(a))#define mem1(a) memset(a,-1,sizeof(a))#define mem(a, b) memset(a, b, sizeof(a))typedef long long ll;const int maxn=100000+10;vector<int>G[maxn];int deep[maxn];int top[maxn]; //top[v]表示v所在的链的顶端结点int siz[maxn]; //siz表示以v为根的子树的结点数int p[maxn]; //p[v]表示v对应的位置int son[maxn]; //重儿子int a[maxn],sumv[4*maxn];int fa[maxn];int u,v,L,R,pos;void init(int n){ for(int i=1;i<=n;i++) G[i].clear(); mem1(son); pos=0;}void dfs1(int u,int pre,int d){ //第一遍dfs求出fa,deep,siz,son deep[u]=d; fa[u]=pre; siz[u]=1; for(int i=0;i<G[u].size();i++){ int v=G[u][i]; if(v!=pre){ dfs1(v,u,d+1); siz[u]+=siz[v]; if(son[u]==-1||siz[v]>siz[son[u]]) son[u]=v; } }}void getpos(int u,int sp){ //第二遍dfs求出top和p top[u]=sp; p[u]=++pos; if(son[u]==-1) return; getpos(son[u],sp); //先遍历重莲,重莲的顶端结点为其父亲的顶端结点 for(int i=0;i<G[u].size();i++){ int v=G[u][i]; if(v!=son[u]&&v!=fa[u]) getpos(v,v); //轻链的顶端节点ei自己 }}void pushup(int rt){ sumv[rt]=sumv[rt<<1]^sumv[rt<<1|1];}void build(int l,int r,int rt){ sumv[rt]=0; if(l==r) return ; int m=(l+r)>>1; build(lson); build(rson);}void update(int l,int r,int rt){ if(l==r){ sumv[rt]=v; return ; } int m=(l+r)>>1; if(u<=m) update(lson); else update(rson); pushup(rt);}int query(int l,int r,int rt){ int res=0; if(L<=l&&R>=r){ return sumv[rt]; } int m=(l+r)>>1; if(L<=m){ res^=query(lson); } if(R>m){ res^=query(rson); } return res;}int find(int u,int v){ int f1=top[u],f2=top[v]; int sum=0; while(f1!=f2){ if(deep[f1]<deep[f2]){ swap(f1,f2); swap(u,v); } L=p[f1]; R=p[u]; sum^=query(1,pos,1); u=fa[f1]; f1=top[u]; } if(deep[u]>deep[v]) swap(u,v); L=p[u]; R=p[v]; sum^=query(1,pos,1); return sum;}int main(){ int n,t,Q; scanf("%d",&t); while(t--){ scanf("%d%d",&n,&Q); init(n); for(int i=1;i<n;i++){ scanf("%d%d",&u,&v); G[u].push_back(v); G[v].push_back(u); } for(int i=1;i<=n;i++) scanf("%d",&a[i]); dfs1(1,1,0); getpos(1,1); build(1,pos,1); for(int i=1;i<=n;i++){ u=p[i]; v=a[i]+1; update(1,pos,1); } int op; while(Q--){ scanf("%d%d%d",&op,&u,&v); if(op==1){ int ans=find(u,v); if(ans==0) printf("-1\n"); else printf("%d\n",ans-1); } else{ u=p[u]; v++; update(1,pos,1); } } } return 0;}
0 0
- hdu5274 Dylans loves tree
- HDU5274.Dylans loves tree
- hdu5274 - Dylans loves tree(树链剖分)
- hdu5274 Dylans loves tree LCA+线段树
- HDU5274 Dylans loves tree(树链剖分线段树)
- HDU5274 Dylans loves tree(树链剖分+异或)
- HDU5274 Dylans loves tree(树链剖分)很巧的点权更新
- HDOJ 5274 Dylans loves tree
- BestCoder #45 1003 Dylans loves tree
- 【线段树】 HDOJ 5274 Dylans loves tree
- hdu 5274 Dylans loves tree 树剖
- HDU 5274 Dylans loves tree 树链剖分(水)
- hdu 5274 Dylans loves tree && BestCoder Round #45
- Dylans loves numbers
- Dylans loves sequence
- HDU5273-Dylans loves sequence
- HDU5273--Dylans loves sequence
- HDU 5272 Dylans loves numbers
- Python下opencv使用笔记
- 动态加载和静态加载
- MySQL优化之group by
- 网上书店系统
- nginx安全下载模块ngx_http_secure_link_module
- HDU5274.Dylans loves tree
- TOMCAT内存的设置
- android-Ultra-Pull-To-Refresh使用教程集锦
- activemq断线重连
- DataRow 包含字段
- 为什么要使用ZooKeeper
- Android基础篇之Activity(五)-onNewIntent()方法
- MySQL优化之distinct
- java.lang.management.ManagementFactory的JAVA属性