zoukankan      html  css  js  c++  java
  • 洛谷 P3359 改造异或树

    传送门
    30分做法:(边权为0)
    我一开始就在想30分做法,然后就想到了:
    首先老套路,正着删边就是倒着加边。
    并查集维护连通块大小,每次加边后将两个端点的size值乘起来累加答案。
    20分做法:
    当n<=1000时,利用xor的一个性质:a^x^x=a;
    然后就可以选取一个根,一遍dfs,预处理出来每个点到根节点的距离,这样dist[x,y]=s[x]^s[y];
    可以每次修改后暴力查找,然后随便搞搞就好了。
    50分做法:
    结合做法1和做法2。
    100分做法:
    给每一个块都建一个平衡树(由于我太蒟蒻了,就不自己手写了,我就用map了,虽然map慢到爆炸,但也可以将就着用吧),在每一次修改的时候用启发式合并,一边合并一边统计答案,就完美解决了。
    代码:(最慢的点400ms)

    #include<map>
    #include<cstdio>
    #define ll long long
    using namespace std;
    inline int read(){
        int x=0;char ch=' ';
        while(ch<'0'||ch>'9')ch=getchar();
        while(ch>='0'&&ch<='9')x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
        return x;
    }
    struct edge{
        int to,next,w;
    }e[200001];
    map<int,int> mp[100001];
    map<int,int>::iterator it;
    int n,tot,x[100001],y[100001],add[100001],fa[100001],z[100001],head[100001],s[100001];
    ll sum[100001],ans;
    
    int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);}
    inline void addedge(int x,int y,int w){e[++tot].to=y;e[tot].next=head[x];e[tot].w=w;head[x]=tot;}
    void dfs(int x,int fa){
        for(int i=head[x];i;i=e[i].next){
            int u=e[i].to;
            if(u!=fa){
                s[u]=s[x]^e[i].w;
                dfs(u,x);
            }
        }
    }
    
    int main(){
        n=read();
        for(int i=1;i<=n;i++)fa[i]=i;
        for(int i=1;i<n;i++){
            x[i]=read();y[i]=read();z[i]=read();
            addedge(x[i],y[i],z[i]);addedge(y[i],x[i],z[i]);
        }
        for(int i=1;i<n;i++){add[i]=read();}
        dfs(1,0);
        for(int i=1;i<=n;i++)mp[i][s[i]]=1;
        for(int i=n-1;i>=1;i--){
            int u=find(x[add[i]]);int v=find(y[add[i]]);
            if(mp[u].size()>mp[v].size())swap(u,v);
            fa[u]=v;
            for(it=mp[u].begin();it!=mp[u].end();++it){
                ans+=1ll*mp[v][it->first]*it->second;
                mp[v][it->first]+=it->second;
            }
            sum[i]=ans;
        }
        for(int i=1;i<=n;i++)printf("%lld
    ",sum[i]);
        return 0;
    }
  • 相关阅读:
    02-02:springboot 整合filter
    02-01:springboot整合servlet开发
    01-SpringBoot项目:helloworld
    SpringBoot
    JavaScript面试题
    vue的生命周期
    小程序下的兼容性问题
    短短几行css代码实现滚动条效果
    Apache服务器的安装和配置
    闭包
  • 原文地址:https://www.cnblogs.com/stone41123/p/7581245.html
Copyright © 2011-2022 走看看