标签:map 点分治 char log 区间 logs out ios pre
输出需要包含 q 行,每行包含 1 个非负整数,表示这名旅行者可以保留的最大幸运值。
正解:树链剖分+线段树套线性基。
这题好劲啊。。$O(nlog^{4}n)$的算法还是很刚的。
这题我们是要求树上路径异或最大值,且这个异或是任意选数异或的,所以我们可以自然地想到线性基。然后我们必须要区间线性基,所以我们在外面套一个线段树。然后这题是在树上的操作,所以写树链剖分。然后这题就做完了。。
这题似乎还有个更优秀的点分治做法,复杂度只要$O(nlog^{2}n)$,似乎很优秀啊。。先填个坑吧。。
1 //It is made by wfj_2048~ 2 #include <algorithm> 3 #include <iostream> 4 #include <complex> 5 #include <cstring> 6 #include <cstdlib> 7 #include <cstdio> 8 #include <vector> 9 #include <cmath> 10 #include <queue> 11 #include <stack> 12 #include <map> 13 #include <set> 14 #define inf (1<<30) 15 #define N (20010) 16 #define ls (x<<1) 17 #define rs (x<<1|1) 18 #define il inline 19 #define RG register 20 #define ll long long 21 #define File(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout) 22 23 using namespace std; 24 25 struct edge{ ll nt,to; }g[2*N]; 26 struct node{ ll l,r; }q[N]; 27 28 ll head[N],top[N],fa[N],son[N],dep[N],sz[N],tid[N],pos[N],n,Q,num,cnt; 29 ll sum[4*N][62],ss[62],xx[62],a[N]; 30 31 il ll gi(){ 32 RG ll x=0,q=1; RG char ch=getchar(); 33 while ((ch<‘0‘ || ch>‘9‘) && ch!=‘-‘) ch=getchar(); 34 if (ch==‘-‘) q=-1,ch=getchar(); 35 while (ch>=‘0‘ && ch<=‘9‘) x=x*10+ch-48,ch=getchar(); 36 return q*x; 37 } 38 39 il ll gll(){ 40 RG ll x=0,q=1; RG char ch=getchar(); 41 while ((ch<‘0‘ || ch>‘9‘) && ch!=‘-‘) ch=getchar(); 42 if (ch==‘-‘) q=-1,ch=getchar(); 43 while (ch>=‘0‘ && ch<=‘9‘) x=x*10+ch-48,ch=getchar(); 44 return q*x; 45 } 46 47 il void insert(RG ll from,RG ll to){ g[++num]=(edge){head[from],to},head[from]=num;return; } 48 49 il void dfs1(RG ll x,RG ll p){ 50 fa[x]=p,dep[x]=dep[p]+1,sz[x]=1; RG ll v; 51 for (RG ll i=head[x];i;i=g[i].nt){ 52 v=g[i].to; if (v==p) continue; 53 dfs1(v,x); sz[x]+=sz[v]; 54 if (sz[son[x]]<=sz[v]) son[x]=v; 55 } 56 return; 57 } 58 59 il void dfs2(RG ll x,RG ll p,RG ll anc){ 60 top[x]=anc,tid[x]=++cnt,pos[cnt]=x; 61 if (son[x]) dfs2(son[x],x,anc); RG ll v; 62 for (RG ll i=head[x];i;i=g[i].nt){ 63 v=g[i].to; if (v==p || v==son[x]) continue; 64 dfs2(v,x,v); 65 } 66 return; 67 } 68 69 il void ins(ll *p,RG ll x){ 70 for (RG ll i=60;i>=0;--i) 71 if (x>>i&1){ 72 if (!p[i]){ p[i]=x; break; } 73 x^=p[i]; 74 } 75 return; 76 } 77 78 il void merge(ll *a,ll *b){ 79 for (RG ll i=60;i>=0;--i) 80 if (b[i]) ins(a,b[i]); 81 return; 82 } 83 84 il ll getmax(ll *p){ 85 RG ll res=0; 86 for (RG ll i=60;i>=0;--i) 87 if ((res^p[i])>res) res^=p[i]; 88 return res; 89 } 90 91 il void build(RG ll x,RG ll l,RG ll r){ 92 if (l==r){ ins(sum[x],a[pos[l]]); return; } 93 RG ll mid=(l+r)>>1; build(ls,l,mid),build(rs,mid+1,r); 94 merge(sum[x],sum[ls]),merge(sum[x],sum[rs]); return; 95 } 96 97 il void query(RG ll x,RG ll l,RG ll r,RG ll xl,RG ll xr){ 98 if (xl<=l && r<=xr){ merge(xx,sum[x]); return; } 99 RG ll mid=(l+r)>>1; 100 if (xr<=mid) query(ls,l,mid,xl,xr); 101 else if (xl>mid) query(rs,mid+1,r,xl,xr); 102 else query(ls,l,mid,xl,mid),query(rs,mid+1,r,mid+1,xr); 103 return; 104 } 105 106 il ll Query(RG ll u,RG ll v){ 107 RG ll ccnt=0; 108 while (top[u]!=top[v]){ 109 if (dep[top[u]]<dep[top[v]]) swap(u,v); 110 q[++ccnt].l=tid[top[u]],q[ccnt].r=tid[u]; 111 u=fa[top[u]]; 112 } 113 if (dep[u]>dep[v]) swap(u,v); 114 q[++ccnt].l=tid[u],q[ccnt].r=tid[v]; 115 memset(ss,0,sizeof(ss)); 116 for (RG ll i=1;i<=ccnt;++i){ 117 memset(xx,0,sizeof(xx)); 118 query(1,1,n,q[i].l,q[i].r); 119 merge(ss,xx); 120 } 121 return getmax(ss); 122 } 123 124 il void work(){ 125 n=gi(),Q=gi(); RG ll u,v; 126 for (RG ll i=1;i<=n;++i) a[i]=gll(); 127 for (RG ll i=1;i<n;++i){ 128 u=gi(),v=gi(); 129 insert(u,v),insert(v,u); 130 } 131 dfs1(1,0),dfs2(1,0,1); build(1,1,n); 132 for (RG ll i=1;i<=Q;++i){ 133 u=gi(),v=gi(); 134 printf("%lld\n",Query(u,v)); 135 } 136 return; 137 } 138 139 int main(){ 140 File("number"); 141 work(); 142 return 0; 143 }
标签:map 点分治 char log 区间 logs out ios pre
原文地址:http://www.cnblogs.com/wfj2048/p/6618820.html