传送门

题意

分析

f[u]表示u到根的边的异或

树上两点之间的异或值为f[u]^f[v],

然后将查询用莫队算法分块,每个点插入到字典树中,利用字典树维护两点异或值大于等于M复杂度O(N^(3/2)*logM)

参考 _zidaoziyan

表示又陷入查错的大坑,思路是对的,调不出来,留坑

trick

代码

wa
#include <bits/stdc++.h>
using namespace std; #define ll long long
#define mem(a,b) memset(a,b,sizeof(a))
#define F(i,a,b) for(int i=a;i<=b;++i) const int maxn = 50050;//集合中的数字个数
int ch[20*maxn][2];//节点的边信息
int num[20*maxn];//记录节点的使用次数,删除时要用
//int val[32*maxn];//节点存储的值
int cnt;//树中节点的个数 bitset<20>choose;
int ask;
int f[maxn],vis[maxn];
ll ans[maxn];
vector<pair<int,int> >mp[maxn];
struct node
{
int l,r,id,len;
bool operator<(const node &p)const
{
return len==p.len?r<p.r:len<p.len;
}
}a[maxn]; void bfs(int u)
{
queue<int>q;
q.push(1);
mem(vis,0);
vis[1]=1;f[1]=0;
while(!q.empty())
{
int tmp=q.front();q.pop();
for(int i=0;i<mp[tmp].size();++i)
{
int v=mp[tmp][i].first;
if(vis[v]) continue;
f[v]=f[tmp]^mp[tmp][i].second;
q.push(v);vis[v]=1;
}
}
} inline void init()
{
cnt=1;mem(ch[0],0);//清空树
}
/*
void insert(int x)//在字典树中插入x,和一般字典树操作相同,将x化成二进制插入到字典树
{
int cur=0;
for(int i=29;i>=0;--i)
{
int idx=((x>>i)&1);
if(!ch[cur][idx])
{
mem(ch[cnt],0);
num[cnt]=0;
ch[cur][idx]=cnt++;
//val[cnt++]=0;
}
//printf("ch[%d][%d]=%d\n",cur,idx,ch[cur][idx]);
cur=ch[cur][idx];
num[cur]++;
}
//val[cur]=x;//最后节点插入val
}
*/
void update(int x,int c)
{
int cur=0;
for(int i=17;i>=0;--i)
{
int idx=((x>>i)&1);
if(!ch[cur][idx])
{
mem(ch[cnt],0);
num[cnt]=0;
ch[cur][idx]=cnt++;
}
cur=ch[cur][idx];
num[cur]+=c;
}
} /*
ll query(ll x)//在字典树(数集)中查找和x异或是最大值的元素y,返回y
{
int cur=0;
for(int i=32;i>=0;--i)
{
int idx=(x>>i)&1;
if(ch[cur][idx^1]) cur=ch[cur][idx^1];else cur=ch[cur][idx];
}
return val[cur];
}
*/ int query(int x)//返回移动一位增加/减少的匹配数
//带删除操作的查询
{
int cur=0,idx,ans=0;
for(int i=17;i>=0;--i)
{
if((i<<i)&x) idx=1;else idx=0;
if(!choose[i])
{
if(ch[cur][idx^1]) ans+=num[ch[cur][idx^1]];
if((!ch[cur][idx])||(!num[ch[cur][idx]])) return ans;
cur=ch[cur][idx];
}
else
{
if((!ch[cur][idx^1])||(num[ch[cur][idx^1]]==0)) return ans;
cur=ch[cur][idx^1];
}
//printf("%d\n",ret);
//if(ch[cur][idx^1]&&num[ch[cur][idx^1]]) cur=ch[cur][idx^1];else cur=ch[cur][idx];
}
//printf("val(%d)=%d\n",cur,val[cur]);
return ans;
} /*
int get_ans(int x)
{
int cur=0,ret=0;
for(int i=29;i>=0;--i)
{
int idx=(((x>>i)&1)^1);
if(num[ch[cur][idx]]) cur=ch[cur][idx],ret|=(1<<i);
else cur=ch[cur][idx^1];
}
return ret;
}
*/
void solve()
{
int L=1,R=0;
init();
ll tmp=0;
F(i,1,ask)
{
while(R<a[i].r) {R++;tmp+=query(f[R]);update(f[R],1);}
//printf("tmp1=%lld\n",tmp);
while(R>a[i].r) {update(f[R],-1);tmp-=query(f[R]);R--;}
// printf("tmp2=%lld\n",tmp);
while(L<a[i].l) {update(f[L],-1);tmp-=query(f[L]);L++;}
// printf("tmp3=%lld\n",tmp);
while(L>a[i].l) {L--;tmp+=query(f[L]);update(f[L],1);}
//printf("tmp4=%lld\n",tmp);
//printf("%lld\n",tmp);;
ans[a[i].id]=tmp;
}
} int main()
{
int n,m;
while(scanf("%d %d %d",&n,&m,&ask)!=EOF)
{
int u,v,w,sqr=sqrt(n);choose=m;
F(i,1,n) mp[i].clear();
F(i,1,n-1)
{
scanf("%d %d %d",&u,&v,&w);
mp[u].push_back(pair<int,int>{v,w});
mp[v].push_back(pair<int,int>{u,w});
}
bfs(1);
//F(i,1,n) printf("%d%c",f[i],i==n?'\n':' ');
F(i,1,ask)
{
scanf("%d%d",&a[i].l,&a[i].r);
a[i].id=i;a[i].len=a[i].l/sqr;
}
sort(a+1,a+1+ask);
//F(i,1,ask) printf("%d %d %d\n",a[i].l,a[i].r,a[i].id );
solve();
F(i,1,ask) printf("%lld\n",ans[i]);
}
return 0;
}
//ac
#include<bits/stdc++.h>
using namespace std;
const int maxn=50010;
typedef pair<int,int> PI;
vector<PI>G[maxn];
int a[maxn],unit,q;
bitset <20> cnt;
int vis[maxn];
long long ans[maxn]; struct node{
int l,r,id;
}Q[maxn]; bool cmp(node u,node v){
if(u.l/unit!=v.l/unit)
return u.l/unit<v.l/unit;
return u.r<v.r;
} void bfs(int u){
queue<int>Q;
Q.push(1);
memset(vis,0,sizeof(vis));
vis[1]=1;
while(!Q.empty()){
int u=Q.front();
Q.pop();
for(int i=0;i<G[u].size();i++){
int v=G[u][i].first;
if(vis[v])
continue;
a[v]=a[u]^G[u][i].second;
Q.push(v);
vis[v]=1;
}
}
} struct Trie{
int val[maxn*20],next[maxn*20][2];
int sz;
void init(){
sz=1;
memset(next[0],0,sizeof(next[0]));
} void insert(int num,int x){
int u=0,c;
for(int i=17;i>=0;i--){
if((1<<i)&num)
c=1;
else
c=0;
if(!next[u][c])
memset(next[sz],0,sizeof(next[sz])),val[sz]=0,next[u][c]=sz++;
u=next[u][c];
val[u]+=x;
}
} int query(int num){
int ans=0,c,u=0;
for(int i=17;i>=0;i--){
if((1<<i)&num)
c=1;
else
c=0;
if(cnt[i]==0){
if(next[u][c^1])
ans+=val[next[u][c^1]];
if(!next[u][c]||val[next[u][c]]==0)
return ans;
u=next[u][c];
}
else{
if(!next[u][c^1]||val[next[u][c^1]]==0)
return ans;
u=next[u][c^1];
}
// printf("%d\n",ans);
}
return ans;
}
}; Trie trie;
void solve(){
int L=1,R=0;
trie.init();
long long tmp=0;
for(int i=1;i<=q;i++){
while(R<Q[i].r){
R++;
tmp+=trie.query(a[R]);
trie.insert(a[R],1);
}
//printf("tmp1=%lld\n",tmp); while(R>Q[i].r){
trie.insert(a[R],-1);
tmp-=trie.query(a[R]);
R--;
}
//printf("tmp2=%lld\n",tmp);
while(L<Q[i].l){
trie.insert(a[L],-1);
tmp-=trie.query(a[L]);
L++;
}
// printf("tmp3=%lld\n",tmp );
while(L>Q[i].l){
L--;
tmp+=trie.query(a[L]);
trie.insert(a[L],1);
}
// printf("tmp4=%lld\n", tmp);
ans[Q[i].id]=tmp;
}
} int main(){
int n,m;
while(scanf("%d%d%d",&n,&m,&q)!=EOF){
int u,v,w;
for(int i=1;i<=n;i++)
G[i].clear();
for(int i=1;i<n;i++){
scanf("%d%d%d",&u,&v,&w);
G[u].push_back(PI{v,w});
G[v].push_back(PI{u,w});
}
cnt=m;
a[1]=0,unit=sqrt(n);
bfs(1);
// for(int i=1;i<=n;++i) printf("%d%c",a[i],i==n?'\n':' ');
for(int i=1;i<=q;i++){
scanf("%d%d",&Q[i].l,&Q[i].r);
Q[i].id=i;
}
sort(Q+1,Q+q+1,cmp);
// for(int i=1;i<=q;++i) printf("%d %d %d %d\n",Q[i].l,Q[i].r,Q[i].id);
solve();
for(int i=1;i<=q;i++)
printf("%lld\n",ans[i]);
}
return 0;
}

HDU5589:Tree(莫队+01字典树)的更多相关文章

  1. HDU5589 Tree【分块 01字典树】

    HDU5589 Tree 题意: 给出一棵\(N\)个点的树,每条边有边权,每次询问下标为\([L,R]\)区间内的点能选出多少点对,点对之间的路径上的边权异或和大于\(M\) 题解: 对于两点\(u ...

  2. HDU 6191 2017ACM/ICPC广西邀请赛 J Query on A Tree 可持久化01字典树+dfs序

    题意 给一颗\(n\)个节点的带点权的树,以\(1\)为根节点,\(q\)次询问,每次询问给出2个数\(u\),\(x\),求\(u\)的子树中的点上的值与\(x\)异或的值最大为多少 分析 先dfs ...

  3. HDU6191 Query on A Tre【dsu on tree + 01字典树】

    Query on A Tree Problem Description Monkey A lives on a tree, he always plays on this tree. One day, ...

  4. HDU6191 Query on A Tree (01字典树+启发式合并)

    题意: 给你一棵1e5的有根树,每个节点有点权,1e5个询问(u,x),问你子树u中与x异或最大的值是多少 思路: 自下而上启发式合并01字典树,注意合并时清空trie 线段树.字典树这种结构确定的数 ...

  5. HDU6191(01字典树启发式合并)

    Query on A Tree Time Limit: 20000/10000 MS (Java/Others)    Memory Limit: 132768/132768 K (Java/Othe ...

  6. Chip Factory(01字典树)

    Chip Factory http://acm.hdu.edu.cn/showproblem.php?pid=5536 Time Limit: 18000/9000 MS (Java/Others)  ...

  7. HDU 4757 Tree(可持久化字典树)(2013 ACM/ICPC Asia Regional Nanjing Online)

    Problem Description   Zero and One are good friends who always have fun with each other. This time, ...

  8. 2014百度之星资格赛—— Xor Sum(01字典树)

    Xor Sum Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 132768/132768 K (Java/Others) Total ...

  9. AcWing:144. 最长异或值路径(dfs + 01字典树)

    给定一个树,树上的边都具有权值. 树中一条路径的异或长度被定义为路径上所有边的权值的异或和: ⊕ 为异或符号. 给定上述的具有n个节点的树,你能找到异或长度最大的路径吗? 输入格式 第一行包含整数n, ...

随机推荐

  1. cocos2d-x-3.6 引擎概述

    cocos2d-x是一个游戏开发引擎,从公布到如今也有五六年了,一路看它慢慢壮大.它是如今应用最多的开源2d引擎,没有之中的一个,据说已经占据90%的市场,所以.对于想从事游戏开发的童鞋来说还是有必要 ...

  2. C++中的数组array和vector,lambda表达式,C字符串加操作,C++中新类型数组(数组缓存),多元数组,new缓冲

     使用C++风格的数组.不须要管理内存. array要注意不要溢出,由于它是栈上开辟内存. array适用于不论什么类型 #include<iostream> #include< ...

  3. linux 输入子系统(4) intput_dev 接口描述

    Name struct input_dev - represents an input device Synopsis struct input_dev { const char * name; // ...

  4. SpringMVC 学习笔记(四) 处理模型数据

    Spring MVC 提供了下面几种途径输出模型数据: – ModelAndView: 处理方法返回值类型为 ModelAndView时, 方法体就可以通过该对象加入模型数据 – Map及Model: ...

  5. JavaScript数组的某些操作(一)

    在软件开发的过程中JavaScript的编程在所难免.当中对数组的操作尤为常见,这里介绍一下和JavaScript数组相关的某些操作: 1.删除并返回数组的第一个元素--shift方法: <!D ...

  6. IE67下float左右对齐

    例子: <style> .h1{text-align: left;} .leftA{color: #000} .rightA{color: #ccc; float: right;} < ...

  7. HDU 5627Clarke and MST

    Clarke and MST Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)To ...

  8. java在某个日期上添加n天的方法实现

    //得到添加n天后的时间字符串 public String getAddDate(Date date,int n){ //格式转换 SimpleDateFormat sdf = new SimpleD ...

  9. EOS智能合约为何选择Web Assembly(wasm)

    比特币的程序非常简单,由解锁脚本和锁定脚本构成.以太坊有智能合约,有图灵完备的虚拟机EVM,但是指令也相对简单,且自成一套.这两种程序本质上都是脚本程序,即由程序翻译指令并执行,而不是由本地机器CPU ...

  10. ubuntu 源、codename 与 sources.list 文件

    查看 codename $ lsb_release -a No LSB modules are available. Distributor ID: Ubuntu Description: Ubunt ...