A1486. 树(王康宁)
题目:http://www.tsinsen.com/A1486
题解:
其实看到和路径有关的就应该想到点分治。
我们找出重心之后遍历每一棵子树得到它的 { x=经过特殊点的个数,y=到rt的异或和}
然后我们按x排序,维护两个头尾指针不断把满足条件的加入trie,然后把左边的放进trie里查询。
但是还有一个问题,所取的两个点不能位于同一棵子树!!!
我yy了一个做法。我们在用三元组来记录{ x=经过特殊点的个数,y=到rt的异或和,ch=所属子树}
然后往trie里插的时候,每条边保留两个ch表示有哪个子树的点从trie往下经过了这里。必须保证这两个ch不同。
然后查询的时候就判断就行了。注意任何时刻往下走的时候都要判断可行性,否则直接返回-1.
代码:
1 #include<cstdio> 2 #include<cstdlib> 3 #include<cmath> 4 #include<cstring> 5 #include<algorithm> 6 #include<iostream> 7 #include<vector> 8 #include<map> 9 #include<set> 10 #include<queue> 11 #include<string> 12 #define inf 1000000000 13 #define maxn 250000+5 14 #define maxm 8000000+5 15 #define eps 1e-10 16 #define ll long long 17 #define ull unsigned long long 18 #define pa pair<int,int> 19 #define for0(i,n) for(int i=0;i<=(n);i++) 20 #define for1(i,n) for(int i=1;i<=(n);i++) 21 #define for2(i,x,y) for(int i=(x);i<=(y);i++) 22 #define for3(i,x,y) for(int i=(x);i>=(y);i--) 23 #define for4(i,x) for(int i=head[x],y=e[i].go;i;i=e[i].next,y=e[i].go) 24 #define for5(n,m) for(int i=1;i<=n;i++)for(int j=1;j<=m;j++) 25 #define mod 1000000007 26 #define lch k<<1,l,mid 27 #define rch k<<1|1,mid+1,r 28 #define sqr(x) (x)*(x) 29 using namespace std; 30 inline int read() 31 { 32 int x=0,f=1;char ch=getchar(); 33 while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} 34 while(ch>='0'&&ch<='9'){x=10*x+ch-'0';ch=getchar();} 35 return x*f; 36 } 37 int n,m,k,cnt,tot,head[maxn],v[maxn],w[maxn],t[maxm][2][3],s[maxn],f[maxn],sum,rt,ans=-1; 38 bool del[maxn]; 39 struct edge{int go,next;}e[2*maxn]; 40 struct rec{int x,y,ch;}a[maxn]; 41 inline bool cmp(rec a,rec b){return a.x<b.x;} 42 inline void add(int x,int y) 43 { 44 e[++tot]=(edge){y,head[x]};head[x]=tot; 45 e[++tot]=(edge){x,head[y]};head[y]=tot; 46 } 47 inline void insert(int y,int ch) 48 { 49 int x=0; 50 for3(i,30,0) 51 { 52 int j=y>>i&1; 53 if(!t[x][j][0])t[x][j][0]=++tot,t[x][j][1]=ch; 54 else if(t[x][j][1]!=ch)t[x][j][2]=ch; 55 x=t[x][j][0]; 56 } 57 } 58 inline int query(int y,int ch) 59 { 60 int x=0,ret=0; 61 for3(i,30,0) 62 { 63 int j=y>>i&1^1; 64 if(t[x][j][0]&&((t[x][j][1]&&t[x][j][1]!=ch)||(t[x][j][2]&&t[x][j][2]!=ch)))ret^=1<<i,x=t[x][j][0]; 65 else 66 { 67 j^=1; 68 if(t[x][j][0]&&((t[x][j][1]&&t[x][j][1]!=ch)||(t[x][j][2]&&t[x][j][2]!=ch)))x=t[x][j][0]; 69 else return -1; 70 } 71 } 72 return ret; 73 } 74 inline void getdep(int x,int fa,int w1,int w2,int w3) 75 { 76 a[++cnt]=(rec){w1,w2,w3}; 77 for4(i,x)if(!del[y]&&y!=fa)getdep(y,x,w1+v[y],w2^w[y],w3); 78 } 79 inline void getrt(int x,int fa) 80 { 81 s[x]=1;f[x]=0; 82 for4(i,x)if(!del[y]&&y!=fa) 83 { 84 getrt(y,x); 85 s[x]+=s[y]; 86 f[x]=max(f[x],s[y]); 87 } 88 f[x]=max(f[x],sum-s[x]); 89 if(f[x]<f[rt])rt=x; 90 } 91 inline void work(int x) 92 { 93 del[x]=1;cnt=0; 94 for4(i,x)if(!del[y])getdep(y,x,v[x]+v[y],w[x]^w[y],y); 95 sort(a+1,a+cnt+1,cmp); 96 int tmp=k+v[x],j=cnt; 97 for1(i,cnt) 98 { 99 while(j>i&&a[i].x+a[j].x>=tmp)insert(a[j].y,a[j].ch),j--; 100 ans=max(ans,query(a[i].y^w[x],a[i].ch)); 101 } 102 for1(i,cnt)if(a[i].x>=k)ans=max(ans,a[i].y); 103 for0(i,tot)t[i][0][0]=t[i][0][1]=t[i][0][2]=t[i][1][0]=t[i][1][1]=t[i][1][2]=0; 104 tot=0; 105 for4(i,x)if(!del[y]) 106 { 107 sum=s[y];rt=0; 108 getrt(y,x); 109 work(rt); 110 } 111 } 112 int main() 113 { 114 freopen("input.txt","r",stdin); 115 freopen("output.txt","w",stdout); 116 n=read();k=read(); 117 for1(i,n)v[i]=read(); 118 for1(i,n)w[i]=read(); 119 for1(i,n-1)add(read(),read()); 120 tot=0; 121 sum=n; 122 f[rt=0]=inf; 123 getrt(1,0); 124 work(rt); 125 for1(i,n)if(v[i]>=k)ans=max(ans,w[i]); 126 cout<<ans<<endl; 127 return 0; 128 }