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 }

时间: 2024-10-10 09:49:27

A1486. 树(王康宁)的相关文章

tsinsen A1486. 树(王康宁) 边分治+字典树

不知为何,这个代码只能得95分 放一下傻逼代码... #include<iostream> #include<cstdio> #include<algorithm> #include<cstring> using namespace std; int n,K; int nn2=1,nn=1,nod; #define N 1000000 #define ed(x) (x>>1) #define ab(x) ((x)>0?(x):-(x)) i

【Tsinsen-A1486】树(王康宁) 点分治 + Trie

A1486. 树(王康宁) 时间限制:1.0s   内存限制:512.0MB 总提交次数:455   AC次数:97   平均分:52.62 查看未格式化的试题   提交   试题讨论 试题来源 2013中国国家集训队第二次作业 问题描述 给出一棵N个点的树,每个点有各自的权值,小A想选出一条简单路径,使得这条路径上的点的权值的异或和最大.另外,小A有一些喜欢的点,他希望在这条路径上经过至少K个自己喜欢的点. 输入格式 第一行包括两个整数N, K,分别表示树的点数和路径上至少包含的小A喜欢的点的

Tsinsen A1486. 树(王康宁)

Description 一棵树,问至少有 \(k\) 个黑点的路径最大异或和. Sol 点分治. 用点分治找重心控制树高就不说了,主要是对答案的统计的地方. 将所有路径按点的个数排序. 可以发现当左端点递增的时候右端点单调递减,时刻满足Trie树里的所有元素都是合法的即可,不断把右端点丢进去,用左端点统计答案. 主要跨越根的时候根的贡献计算了两次,需要删掉一次. 对于需要满足不是一颗子树,可以将Trie树上的节点打一个标记,表示这个节点及其子节点都是在某子树下的路径,子树个数大于1的时候这个标记

A1487. 分配游戏(王康宁)

把题目所给的三元组看成三维空间里的点坐标,记录下来每个点在每个坐标平面上的映射,对于每一个询问,查询每个面上分别有多少个点在该点的映射与原点所组成的矩形内部 原先想到二维树状数组,然而老爷吃着鸡块说了一句空间炸了,,,于是炸了 然后发现其实还是在树状数组上lg,但是要把插入和询问和(huo)在一起,按其中一维排序,先询问后查询 膜一下fatheryoung,码代码神快,神稳 风格分不及格,,,贴代码好方 1 #include<bits/stdc++.h> 2 using namespace s

树分治 复习总结

前几天去填重建计划的坑的时候无意中发现自己的树分治一直有一个地方有点bug,是错误的QAQ(但是貌似影响不大 于是皇德耀世,赶紧去找了几道树分治来练习一下 bug是每次树分治找重心的时候sum直接用的w数组,可是对于每一层w数组要重新计算(然而我并没有QAQ WC2010 重建计划 这是一份bug重重的代码,我用了19min写完,交上去1A 可是我后来发现这份代码至少有三处错误QAQ数据也太弱了吧 贴一份bug重重的代码吧,顺便锻炼找bug能力? 做法是二分答案之后每条边-mid,判断条件是是否

【资料】国家集训队论文集(1999~2014)

本文版权归ACShiryu和acvay所有,如转载请注明原作者. 国家集训队1999论文集 1.陈宏:<数据结构的选择与算法效率--从IOI98试题PICTURE谈起> 2.来煜坤:<把握本质,灵活运用--动态规划的深入探讨> 3.齐鑫:<搜索方法中的剪枝优化> 4.邵铮:<数学模型的建立.比较和应用> 5.石润婷:<隐蔽化.多维化.开放化--论当今信息学竞赛中数学建模的灵活性> 6.杨帆:<准确性.全面性.美观性--测试数据设计中的三要素

王学长的AAA树

让我们响应王学长的号召勇敢的分开写splay和lct吧! 分开写大法好!!!!!!!!!!!杜教的ch[4]弱爆了!!!! 1 #include <stdio.h> 2 #include <algorithm> 3 char ch; 4 inline void read(int &x) 5 { 6 x=0;ch=getchar(); 7 while(ch<=32) ch=getchar(); 8 while(ch>32) x=x*10+ch-48,ch=getc

bzoj:4209: 西瓜王

原题链接:http://www.lydsy.com/JudgeOnline/problem.php?id=4209 (虽然仅仅是看在名字的份上,我们还是得说这题是一道) 绝世好题!西瓜王!西瓜王!西瓜王![wàng] 说点正经的,一开始以为合成圣堂的时候必须相邻的,然后变成了区间内取k个数不能相邻的数的最大总价值,诶我的瓜妈妈呀,不会做啊-- 看一下CA爷blog:贪心,然后替换-- 诶,我看错题了? 最后就是主席树维护一下区间前k大的总价值,再查一下这最大的k个里面有多少个奇数多少偶数,如果奇

数据结构之AVL树

说明:本文仅供学习交流,转载请标明出处,欢迎转载! 在前面的博文中,我们已经介绍了数据结构之二分查找树的相关知识,二分查找的提出主要是为了提高数据的查找效率.同一个元素集合可以对应不同的二分查找树BST,二分查找树的形态依赖于元素的插入顺序.同时我们也已经知道,如果将一个有序的数据集依次插入到二查找树中,此时二分查找树将退化为线性表,此时查找的时间复杂度为o(n).为了防止这一问题的出现,便有了平衡二叉树的存在价值.平衡二叉树从根本上将是为了防止出现斜二叉树的出现,从而进一步提高元素的查找效率,