3 条题解

  • 3
    @ 2021-11-4 17:27:33

    从洛谷 P4551 最长异或路径 过来的

    通过那个题的结论我们可以知道 dist(x,y)=dist(x,rt) dist(x,y)=dist(x,rt) ^ dist(rt,y) dist(rt,y)

    首先可以对问题化简,我们先来看一个题

    给定序列 A,求 i<j i < j Ai<Aj A_i < A_j 的个数

    按照 j[1,n] j \in [1,n] 的顺序扫一遍,每次先查询当前 trie 中与 valj val_j

    异或结果 >=k >= k 的数量(直接 trie 上二分贪心即可),

    然后把 valj val_j 加入 trie 中

    那么这个题,我们可以 dfs 预处理出 dist(rt,u)(u[1,n]) dist(rt,u) ( u∈[1,n] )

    然后问题就转化成了上面那个问题

    Talking  is  cheap,  show  the  code. Talking \; is \; cheap , \; show \; the \; code.

    #include <algorithm>
    #include <iostream>
    #include <cstring>
    #include <vector>
    #include <cstdio>
    #include <cmath>
    using namespace std;
    
    #define int long long
    
    /***** Fast_IO *****/
    
    using std::cin;
    using std::cout;
    using vii = std::vector<int> ;
    using pii = std::pair<int,int> ;
    
    namespace IO{
    	char buf[(1<<21)],*p1=buf,*p2=buf,buf1[(1<<21)]; int _=0;
    
    	inline char gc (){
    		return p1==p2&&(p2=(p1=buf)+fread(buf,1,(1<<21),stdin),p1==p2)?EOF:*p1++;
    	}
    
    	#define gc getchar
    	#define pc putchar
    	#define ONLINE_JUDGE OJ
    
    	template<class I>
    	inline I read(I &x){
    		x=0; I f=1; char c=gc(); if(c==EOF){ return -1; }
    		while(c<'0'||c>'9'){ if(c=='-'){ f=f*(-1); } c=gc(); }
    		while(c>='0'&&c<='9'){ x=(x<<1)+(x<<3)+(c^48); c=gc(); }
    		return x=x*f;
    	}
    
    	template<typename I,typename ...Args>
    	inline void read(I &a, Args &...args){
    		read(a),read(args...);
    	}
    
    	template<class I>
    	inline void write(I x){
    		if(x==0){ pc('0'); return; }
    		int tmp=x>0?x:(-x),cnt=0;
    		if(x<0){ pc('-'); }
    		while(tmp){ buf[cnt++]=(tmp%10)+'0'; tmp/=10; }
    		while(cnt){ pc(buf[--cnt]); }
    		return;
    	}
    
    	void _FILE(){
    		#ifndef ONLINE_JUDGE
    			freopen("text.in","r",stdin);
    			freopen("text.out","w",stdout);
    		#endif
    	}
    	
    	template<class I>
    	inline void chmax(I &x,I y){ return x=max(x,y),void(); }
    	
    	template<class I>
    	inline void chmin(I &x,I y){ return x=min(x,y),void(); }
    
    	#define out(x) write(x),pc(' ')
    	#define outn(x) write(x),pc('\n')
    	#define assi() pc('\t')
    	#define FOR(i,a,b) for(int i(a);i<=(b);++i)
    	#define ROF(i,a,b) for(int i(a);i>=(b);--i)
    	#define FORs(i,a,b,s) for(int i(a);i<=(b);i+=(s))
    	#define ROFs(i,a,b,s) for(int i(a);i>=(b);i-=(s))
    	#define next(i,now) for(int i(link[now]);i;i=edge[i].nexty)
    	#define each(i,v) for(auto &i:v)
    	#define all(v) v.begin(),v.end()
    	#define sqr(k) ((k)*(k))
    	#define inf 0x3f3f3f3f
    	#define pb push_back
    	#define mp make_pair
    	#define fir first
    	#define sec second
    }using namespace IO;
    
    /***** Fast_IO *****/
    
    #define maxn 1000010
    #define SIZE 5010
    
    int n,k;
    
    namespace GRA{
    	struct Edge{ int start,end,val,nexty; }edge[(maxn)<<1];
    
    	int link[maxn],edge_cnt;
    
    	void add_edge(int u,int v,int w){
    		edge[++edge_cnt]=(Edge){u,v,w,link[u]};
    		link[u]=edge_cnt;
    	}
    }using namespace GRA;
    
    int DIGIT(int S,int k){ return S>>(k-1)&1; }
    
    class Trie{
    	private:
    		struct Trie_tree{ int son[2],cnt; }trie[(maxn)<<5];
    
    		int trie_cnt=1;
    
    	public:
    		void insert(int S){
    			int u=1,v=0;
    			ROF(i,32,1){
    				++trie[u].cnt;
    				v=DIGIT(S,i);
    				(!trie[u].son[v])&&
    				(trie[u].son[v]=++trie_cnt);
    				u=trie[u].son[v];
    			}
    			++trie[u].cnt;
    		}
    
    		int query(int S){
    			int res=0;
    			int u=1,v1=0,v2=0;
    			ROF(i,32,1){
    				v1=DIGIT(S,i);
    				v2=DIGIT(k,i);
    				// (v2==0)&&(outn(trie[trie[u].son[v1^1]].cnt));
    				(v2==0)&&(res+=trie[trie[u].son[v1^1]].cnt);
    				(v2==0)&&(u=trie[u].son[v1]);
    				(v2==1)&&(u=trie[u].son[v1^1]);
    			}
    			return (res+=trie[u].cnt);
    		}
    }tr;
    
    int val[maxn];
    
    void dfs(int now,int fa){
    	next(i,now){
    		int ver=edge[i].end;
    		if(ver==fa){ continue; }
    		val[ver]=val[now]^edge[i].val;
    		dfs(ver,now);
    	} return;
    }
    
    signed main(){
    	_FILE();
    	read(n,k);
    	FOR(i,1,n-1){
    		int u,v,w;
    		read(u,v,w);
    		add_edge(u,v,w);
    		add_edge(v,u,w);
    	}
    	dfs(1,0);
    	// FOR(i,1,n){ read(val[i]); }
    	int res=0;
    	FOR(i,1,n){ res+=tr.query(val[i]); tr.insert(val[i]); }
    	outn(res);
    	return 0;
    }
    
    /*
    3 2
    1 2 3
    */
    
    
    • 2
      @ 2021-10-5 9:04:13
      //考虑两个相同的数异或为0
      //所以dis(x,y)=dis(1,x)^dis(1,y)
      //直接01trie维护就好了
      #include<bits/stdc++.h>
      using namespace std;
      const int N=1e6+5;
      vector<int> e[N],g[N];
      int n,k,tr[N*30][2],s[N*30],tot=1;
      long long sum;
      void add(int x){
         int now=1;
         for(int i=30;i>=0;i--){
            s[now]++;
            int p=(x>>i)&1;
            if(!tr[now][p])tr[now][p]=++tot;
            now=tr[now][p];
         }
         s[now]++;
      }
      int ask(int x){
         int now=1,ans=0;
         for(int i=30;i>=0;i--){
            int p=(x>>i)&1;
            int q=(k>>i)&1;
            if(q==0) ans+=s[tr[now][p^1]],now=tr[now][p];
            else now=tr[now][p^1];
         }
         return ans+s[now];
      }
      void dfs(int x,int fa,int s){
         sum+=ask(s);
         add(s);
         for(int i=0;i<e[x].size();i++){
            int y=e[x][i],z=g[x][i]; 
            if(y==fa)continue;
            dfs(y,x,s^z);
         }
      }
      int main(){
         scanf("%d%d",&n,&k);
         for(int i=1;i<n;i++){
            int x,y,z;
            scanf("%d%d%d",&x,&y,&z);
            e[x].push_back(y),g[x].push_back(z);
            e[y].push_back(x),g[y].push_back(z);
         }
         dfs(1,0,0);
         printf("%lld",sum);
         return 0;
      }
      
      • 0
        @ 2023-3-25 9:35:28
        #include<bits/stdc++.h>
        using namespace std;
        const int N=1e6+5;
        vector<int> e[N],g[N];
        int n,k,tr[N*30][2],s[N*30],tot=1;
        long long sum;
        void add(int x){
        int now=1;
        for(int i=30;i>=0;i--){
        s[now]++;
        int p=(x>>i)&1;
        if(!tr[now][p])tr[now][p]=++tot;
        now=tr[now][p];
        }
        s[now]++;
        }
        int ask(int x){
        int now=1,ans=0;
        for(int i=30;i>=0;i--){
        int p=(x>>i)&1;
        int q=(k>>i)&1;
        if(q==0) ans+=s[tr[now][p^1]],now=tr[now][p];
        else now=tr[now][p^1];
        }
        return ans+s[now];
        }
        void dfs(int x,int fa,int s){
        sum+=ask(s);
        add(s);
        for(int i=0;i<e[x].size();i++){
        int y=e[x][i],z=g[x][i];
        if(y==fa)continue;
        dfs(y,x,s^z);
        }
        }
        int main(){
        scanf("%d%d",&n,&k);
        for(int i=1;i<n;i++){
        int x,y,z;
        scanf("%d%d%d",&x,&y,&z);
        e[x].push_back(y),g[x].push_back(z);
        e[y].push_back(x),g[y].push_back(z);
        }
        dfs(1,0,0);
        printf("%lld",sum);
        return 0;
        }
        
        • 1

        信息

        ID
        93
        时间
        2500ms
        内存
        512MiB
        难度
        4
        标签
        递交数
        1773
        已通过
        82
        上传者