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))
int e2[N],ne2[N],v2[N];
int e[N],ne[N],v[N];
int im[N],val[N];
int num[N];
bool been[N];
void add2(int x,int y){
ne2[++nn2]=e2[x],e2[x]=nn2,v2[nn2]=y;
}
void add(int x,int y){
ne[++nn]=e[x],e[x]=nn,v[nn]=y;
}
int siz[N];
bool vis[N];
int tot;
int wv,u,mi,rt1,rt2;
int bn[2];
int res=-1;
struct P{
int x,y;
P(int a=0,int b=0){
x=a,y=b;
}
bool operator<(P a)const{
return y<a.y;
}
}b[2][N];
void dfs(int x,int y){
siz[y]=1;
for(int i=e[y];i;i=ne[i])if(!vis[i]&&i!=(x^1)){
dfs(i,v[i]);
siz[y]+=siz[v[i]];
}
u=ab(tot-siz[y]*2);
if(x)if(wv==-1||u<mi){
mi=u,wv=x;
}
}
int yy;
void dfs2(int x,int fa,int xx,int kk){
for(int i=e[x];i;i=ne[i])if(fa!=v[i]&&!vis[i]){
dfs2(v[i],x,xx^val[v[i]],kk+im[v[i]]);
}
b[yy][++bn[yy]]=P(xx,kk);
}
int p[N][2],dd;
void cl(){
for(int i=0;i<=dd;i++)p[i][1]=0,p[i][0]=0;
dd=0;
}
void ins(int x){
int now=0;
for(int i=31;i>=1;i--){
u=(x>>i-1)&1;
if(!p[now][u])p[now][u]=++dd;
now=p[now][u];
}
}
int check(int x){
if(!p[0][1]&&!p[0][0])return -1;
int now=0;
int ans=0;
for(int i=31;i>=1;i--){
u=(x>>i-1)&1;
if(p[now][!u]){
ans+=(1<<i-1);
now=p[now][!u];
}else now=p[now][u];
}
return ans;
}
void solv(int x,int wt){
if(wt<2)return;
tot=wt;
wv=-1;
dfs(0,x);
vis[wv]=1;
vis[wv^1]=1;
int a1=v[wv],a2=v[wv^1];
yy=0;
bn[0]=bn[1]=0;
dfs2(a1,0,val[a1],im[a1]);
yy=1;
dfs2(a2,0,val[a2],im[a2]);
sort(b[1]+1,b[1]+bn[1]+1);
sort(b[0]+1,b[0]+bn[0]+1);
cl();
int s1=bn[0];
for(int i=1;i<=bn[1];i++){
while(s1>0&&b[0][s1].y+b[1][i].y>=K){
ins(b[0][s1].x);
s1--;
}
res=max(res,check(b[1][i].x));
}
solv(a1,bn[0]);
solv(a2,bn[1]);
}
void rebuild(int x){
been[x]=1;
if(num[x]>4){
int n1=0;
int u1=++nod;
int u2=++nod;
num[u1]=1;
num[u2]=1;
add(x,u1);
add(u1,x);
add(x,u2);
add(u2,x);
for(int i=e2[x];i;i=ne2[i])if(!been[v2[i]]){
n1++;
if(n1<=((num[x]-1)/2)){
add2(u1,v2[i]);
num[u1]++;
}else{
num[u2]++;
add2(u2,v2[i]);
}
}
rebuild(u1);
rebuild(u2);
}else{
for(int i=e2[x];i;i=ne2[i])if(!been[v2[i]]){
add(x,v2[i]);
add(v2[i],x);
rebuild(v2[i]);
}
}
}
int main(){
scanf("%d%d",&n,&K);
for(int i=1;i<=n;i++){
scanf("%d",&im[i]);
}
for(int i=1;i<=n;i++){
scanf("%d",&val[i]);
}
for(int i=1;i<n;i++){
int a,b;
scanf("%d%d",&a,&b);
add2(a,b);
add2(b,a);
num[a]++;
num[b]++;
}
for(int i=1;i<=n;i++)if(im[i]>=K){
res=max(res,val[i]);
}
nod=n;
rebuild(1);

solv(1,nod);

cout<<res;

}

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

时间: 2025-01-13 10:09:10

tsinsen A1486. 树(王康宁) 边分治+字典树的相关文章

trie树(字典树)

1. trie树,又名字典树,顾名思义,它是可以用来作字符串查找的数据结构,它的查找效率比散列表还要高. trie树的建树: 比如有字符串"ab" ,"adb","adc"   可以建立字典树如图: 树的根节点head不存储信息,它有26个next指针,分别对应着字符a,b,c等.插入字符串ab时,next['a'-'a']即next[0]为空,这是申请一个结点放在next[0]的位置,插入字符串db时,next['d'-'a']即next[3]

LA_3942 LA_4670 从字典树到AC自动机

首先看第一题,一道DP+字典树的题目,具体中文题意和题解见训练指南209页. 初看这题模型还很难想,看过蓝书提示之后发现,这实际上是一个标准DP题目:通过数组来储存后缀节点的出现次数.也就是用一颗字典树从后往前搜一发.最开始觉得这种搞法怕不是要炸时间,当时算成了O(N*N)毕竟1e5的数据不搞直接上N*N的大暴力...后来发现,字典树根本跑不完N因为题目限制字典树最多右100层左右. 实际上这道题旧思想和模型来说很好(因为直观地想半天还真想不出来..)但是实际实现起来很简单--撸一发字典树就好了

字典树模板(java)

class Trie{ private int SIZE=26; private TrieNode root;//字典树的根 Trie(){//初始化字典树 root=new TrieNode(); } private class TrieNode{//字典树节点 private int num;//有多少单词通过这个节点,即节点字符出现的次数 private TrieNode[] son;//所有的儿子节点 private boolean isEnd;//是不是最后一个节点 private c

hdu1251 统计难题 【字典树】

统计难题 Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 131070/65535 K (Java/Others) Total Submission(s): 19292    Accepted Submission(s): 8518 Problem Description Ignatius最近遇到一个难题,老师交给他很多单词(只有小写字母组成,不会有重复的单词出现),现在老师要他统计出以某个字符串为前缀的单词数量(单词本身也是自己的

Algorithms(字典树)

字典树 #ifndef TIRE_H_INCLUDED #define TIRE_H_INCLUDED /* ** 字典树 */ #define MAX 26 typedef struct Node { int num; struct Node* next[MAX]; }Tire; /* ** 创建一个节点 */ Tire* create(void); /* ** 插入一个字符串 */ Tire* insert(char str[], Tire* head); /* ** 搜索字符串 */ in

Trie字典树 静态内存

静态字典树 看了好久的字典树,挺简单的一个结构,愣是看了这么久才写出来... 专心一点就不会这样了.... 接下来就去刷刷字典树的题吧....... 下面是字典树.... 定义节点 typedef struct Trie{ char val;  //其实这东西没啥软用...注释掉也一样...没有变化 bool isword; struct Trie *next[26];}*Trie_pointer; 然后建树 这几天抽风了... 把memset写在函数外面去了.... 编译老半天过不去....

Barty&#39;s Computer 字典树

https://nanti.jisuanke.com/t/17122 Barty have a computer, it can do these two things. Add a new string to its memory, the length of this string is even. For given 44 strings a,b,c,da,b,c,d, find out how many strings that can be product by a+s1+b+c+s2

【codevs3031】最富有的人[字典树]

网址:http://codevs.cn/problem/3031/ 这是蒟蒻写的第一道字典树--听说出市选题的神犇要出字符串,于是就赶紧滚去学了学(然而高精度算字符串算法?) 简单来说,字典树就是把一坨字符串按照字典序储存起来.然而,直接把字符串排序太浪费空间,而且时间效率也不佳.于是,我们就需要字典树了. 字典树的大致存储方式就是: 假设有5个字符串:a,abc,ab,acb,abd,字典树的存储方式就是把两个字符串相同的前缀合并起来(比如abc和abd有公共的前缀ab,那么就把两个ab合并起

比赛之字典树题解

这道题第一眼看见题目所给的时间就有一种预感,仅仅是600ms,运行的算法复杂度稍微高一点就会超时.那么我首先是犯傻想偷偷懒,直接是调用一个系统库函数strstr(),希望它能够完成自己的题目,但是显然是超时的.百度了一下它的实现方法是直接采用没有优化的算法,复杂度是最高的.但是由于自己压根就不会写字典树,所以还是抱着一个侥幸的心态去用KMP算法来实现,结果还是铁铁的超时.那么最后的实现应该是通过什么方式呢? 很显然,这道题是一个很裸的字典树题,直接使用字典树的方式解决是最好的.以后也要将这些最基