您的位置:首页 > 其它

luogu2420 让我们异或和吧

2016-11-11 22:02 232 查看

题目

  https://www.luogu.org/problem/show?pid=2420

题解

  小知识:异或xor 满足结合律、交换律。另外A xor A=0,也就是说A xor B xor C=E,那么B xor C = E xor A,也就是说可以前缀和。

  做法一:树链剖分,线段树维护。复杂度O(Nlog^2N)(注意坑点:因为权值在边上,所以交界处的值不能算进去)

  做法二:树上前缀和,用s[x]表示根节点到x的路径上的权值异或值,那么两个点上路径的异或值就是s[a] xor s[b]。复杂度O(N+M)

  做法三:LCT,把边化成点,然后瞎搞。代码老是TLE....我也没办法啊,毕竟常数大,暂且先这样吧

代码

//树链剖分
#include <cstdio>
#include <algorithm>
#define maxn 200010
using namespace std;
int N, M, head[maxn], next[maxn], to[maxn], tmp[maxn], val[maxn], w[maxn], fa[maxn],
size[maxn], son[maxn], tot, tim, deep[maxn], tid[maxn], top[maxn];
struct segtree
{
int l, r, w;
segtree *lch, *rch;
segtree(){w=0;lch=rch=0;}
}*root;
void adde(int a, int b, int v){to[++tot]=b;w[tot]=v;next[tot]=head[a];head[a]=tot;}
void build(segtree *p, int l, int r)
{
int mid=(l+r)>>1;
p->l=l,p->r=r;
if(l==r){p->w=val[l];return;}
build(p->lch=new segtree,l,mid);
build(p->rch=new segtree,mid+1,r);
p->w=p->lch->w xor p->rch->w;
}
int segsum(segtree *p, int l, int r)
{
int mid=(p->l+p->r)>>1, ans=0;
if(l<=p->l and r>=p->r)return p->w;
if(l<=mid)ans=ans xor segsum(p->lch,l,r);
if(r>mid)ans=ans xor segsum(p->rch,l,r);
return ans;
}
void dfs1(int pos)
{
int p, x;
size[pos]=1;
for(p=head[pos];p;p=next[p])
{
x=to[p];
if(x==fa[pos])continue;
fa[x]=pos;
deep[x]=deep[pos]+1;
tmp[x]=w[p];
dfs1(x);
if(son[pos]==0 or size[x]>size[son[pos]])son[pos]=x;
size[pos]+=size[x];
}
}
void dfs2(int pos, int tp)
{
int p, x;
tid[pos]=++tim;
top[pos]=tp;
if(son[pos])dfs2(son[pos],tp);
for(p=head[pos];p;p=next[p])
{
x=to[p];
if(x==fa[pos] or x==son[pos])continue;
dfs2(x,x);
}
}
int sum(int a, int b)
{
int ta=top[a], tb=top[b], ans=0;
while(ta!=tb)
{
if(deep[ta]<deep[tb])swap(ta,tb),swap(a,b);
ans=ans xor segsum(root,tid[ta],tid[a]);
a=fa[ta];ta=top[a];
}
if(deep[a]>deep[b])swap(a,b);
ans=ans xor segsum(root,tid[a],tid[b]);
ans=ans xor segsum(root,tid[a],tid[a]);
return ans;
}
int main()
{
int i, a, b, c, M;
scanf("%d",&N);
for(i=1;i<N;i++)scanf("%d%d%d",&a,&b,&c),adde(a,b,c),adde(b,a,c);
dfs1(1);
dfs2(1,1);
for(i=1;i<=N;i++)val[tid[i]]=tmp[i];
build(root=new segtree,1,tim);
scanf("%d",&M);
for(i=1;i<=M;i++)
{
scanf("%d%d",&a,&b);
printf("%d\n",sum(a,b));
}
return 0;
}
//树上前缀和
#include <cstdio>
#include <algorithm>
#define maxn 200010
using namespace std;
int N, M, head[maxn], to[maxn], w[maxn], next[maxn], tot, s[maxn];
void adde(int a, int b, int c){to[++tot]=b;w[tot]=c;next[tot]=head[a];head[a]=tot;}
void input()
{
int i, a, b, c;
scanf("%d",&N);
for(i=1;i<N;i++)scanf("%d%d%d",&a,&b,&c),adde(a,b,c),adde(b,a,c);
}
void dfs(int pos, int pre)
{
int p;
for(p=head[pos];p;p=next[p])
{
if(to[p]==pre)continue;
s[to[p]]=s[pos] xor w[p];
dfs(to[p],pos);
}
}
int main()
{
int i, a, b, m;
input();
dfs(1,0);
scanf("%d",&m);
for(i=1;i<=m;i++)
{
scanf("%d%d",&a,&b);
printf("%d\n",s[a] xor s[b]);
}
return 0;
}
//LCT
#include <cstdio>
#include <algorithm>
#define maxn 500000
using namespace std;
int N, M;
struct node
{
int sum, rev, w;
node *f, *ch[2];
}nd[maxn], *s[maxn];
inline int read(int x=0)
{
char c=getchar();
while(c<48 or c>57)c=getchar();
while(c>=48 and c<=57)x=x*10+c-48,c=getchar();
return x;
}
inline int getwh(node *x)
{if(!x->f)return -1;if(x->f->ch[0]==x)return 0;if(x->f->ch[1]==x)return 1;return -1;}
inline bool isroot(node *x){return getwh(x)==-1;}
inline void join(node *x, node *y, int wh){if(x)x->f=y;if(y)y->ch[wh]=x;}
inline void rever(node *x){if(x)x->rev^=1;}
inline void pushdown(node *x)
{
if(x->rev)
{
swap(x->ch[0],x->ch[1]);
rever(x->ch[0]),rever(x->ch[1]);
x->rev=0;
}
}
inline void pushup(node *x)
{
x->sum=x->w;
if(x->ch[0])x->sum^=x->ch[0]->sum;
if(x->ch[1])x->sum^=x->ch[1]->sum;
}
inline void rotate(node *x)
{
node *y=x->f, *z=y->f;
int c=getwh(x);
if(isroot(y))x->f=y->f;else join(x,z,getwh(y));
join(x->ch[!c],y,c);
join(y,x,!c);
pushup(y),pushup(x);
}
inline void splay(node *x)
{
node *y; int top=0;
for(y=x;!isroot(y);y=y->f)s[++top]=y;s[++top]=y;
for(;top;top--)pushdown(s[top]);
while(!isroot(x))
{
y=x->f;
if(isroot(y)){rotate(x);return;}
if(getwh(x)^getwh(y))rotate(x);else rotate(y);
rotate(x);
}
}
inline void access(node *x)
{
node *t=0;
while(x)
{
splay(x);
x->ch[1]=t;
pushup(x);
t=x;x=x->f;
}
}
inline void makeroot(node *x){access(x);splay(x);rever(x);}
inline void link(node *x, node *y){makeroot(x);x->f=y;}
void init()
{
int a, b, c, i;
N=read();
for(i=1;i<N;i++)
{
a=read(),b=read(),c=read();
nd[N+i].w=nd[N+i].sum=c;
link(nd+N+i,nd+a);link(nd+N+i,nd+b);
access(nd+a),splay(nd+a);
}
}
inline int work(int a, int b)
{
makeroot(nd+a),access(nd+b);splay(nd+b);
return nd[b].sum;
}
int main()
{
int a, b;
init();
for(M=read();M;M--)a=read(),b=read(),printf("%d\n",work(a,b));
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: