• #41 最短路(分治+线性基)


      考虑异或最短路应该怎么求。那么这是个WC原题,dfs一遍找到所有有用的环丢进线性基即可,因为每一个环的权值都是可以取到且不对其他部分产生影响的。

      现在给了一棵树,不妨就把他看做原图的dfs树。每增加一条边就是增加了一个环。算出权值后,现在问题变为求一个数和任选一段区间里的数的最大异或值。

      比较暴力的做法是直接建线段树,每次logn*log2v取出区间线性基。这样可以拿50分。

      线性基的合并实在太慢了。考虑能不能离线搞。每次取出跨过区间中点的询问,处理中点左右的后缀前缀线性基,询问时将两边线性基合并。于是就变成logv(logn+logv)了。

      调了半天发现m和n搞反了。

      果然是NOIp模拟。

    #include<iostream> 
    #include<cstdio>
    #include<cmath>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    #include<cassert>
    using namespace std;
    int read()
    {
        int x=0,f=1;char c=getchar();
        while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
        while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
        return x*f;
    }
    #define N 300010
    int n,m,q,p[N],deep[N],value[N],ans[N],t=0;
    struct base
    {
        int size,a[31];
        void ins(int x)
        {
            for (register int i=30;~i;i--)
            {
                if (!x) break;
                if (x&(1<<i))
                if (!a[i]) {a[i]=x;size++;break;}
                else x^=a[i];
            }
        }
        base operator +(const base&b) const
        {
            base c;
            if (size>b.size)
            {
                c.size=size;for (int i=0;i<31;i++) c.a[i]=a[i];
                if (size==31) return c;
                for (register int i=30;~i;i--)
                c.ins(b.a[i]);
            }
            else
            {
                c.size=b.size;for (int i=0;i<31;i++) c.a[i]=b.a[i];
                if (b.size==31) return c;
                for (register int i=30;~i;i--)
                c.ins(a[i]);
            }
            return c;
        }
    }pre[N],suf[N];
    struct data{int to,nxt,len;
    }edge[N<<1];
    struct data2{int i,l,r,x; 
    }Q[N],u[N];
    void addedge(int x,int y,int z){t++;edge[t].to=y,edge[t].nxt=p[x],edge[t].len=z,p[x]=t;}
    void dfs(int k,int from)
    {
        for (int i=p[k];i;i=edge[i].nxt)
        if (edge[i].to!=from)
        {
            deep[edge[i].to]=deep[k]^edge[i].len;
            dfs(edge[i].to,k);
        }
    }
    int work(int x,base p)
    {
        for (int i=30;~i;i--)
        x=min(x,x^p.a[i]);
        return x;
    }
    void solve(int l,int r,int low,int high)
    {
        if (l>r||low>high) return;
        if (low==high)
        {
            for (int i=l;i<=r;i++) ans[Q[i].i]=min(Q[i].x,Q[i].x^value[low]);
            return;
        }
        int mid=low+high>>1;
        for (int i=mid;i>=low;i--)
        {
            if (i==mid) pre[i]=(base){0,{0}};
            else pre[i]=pre[i+1];
            pre[i].ins(value[i]);
        }
        for (int i=mid+1;i<=high;i++)
        {
            if (i==mid+1) suf[i]=(base){0,{0}};
            else suf[i]=suf[i-1];
            suf[i].ins(value[i]);
        }
        int head=l-1,tail=r+1;
        for (int i=l;i<=r;i++)
        if (Q[i].l<=mid&&Q[i].r>mid) ans[Q[i].i]=work(Q[i].x,pre[Q[i].l]+suf[Q[i].r]);
        else if (Q[i].r<=mid) u[++head]=Q[i];
        else u[--tail]=Q[i];
        for (int i=l;i<=r;i++) Q[i]=u[i];
        solve(l,head,low,mid);
        solve(tail,r,mid+1,high);
    }
    int main()
    {
    #ifndef ONLINE_JUDGE
        freopen("c.in","r",stdin);
        freopen("c.out","w",stdout);
        const char LL[]="%I64d
    ";
    #else
        const char LL[]="%lld
    ";
    #endif
        n=read(),m=read(),q=read();
        for (int i=1;i<n;i++)
        {
            int x=read(),y=read(),z=read();
            addedge(x,y,z),addedge(y,x,z);
        }
        dfs(1,1);
        for (int i=1;i<=m;i++)
        {
            int x=read(),y=read(),z=read();
            value[i]=deep[x]^deep[y]^z;
        }
        for (int i=1;i<=q;i++)
        {
            int s=read(),t=read(),l=read(),r=read();
            Q[i].i=i,Q[i].x=deep[s]^deep[t],Q[i].l=l,Q[i].r=r;
        }
        solve(1,q,1,m);
        for (int i=1;i<=q;i++) printf("%d
    ",ans[i]);
        return 0;
    }
  • 相关阅读:
    BNUOJ 12756 Social Holidaying(二分匹配)
    HDU 1114 Piggy-Bank(完全背包)
    HDU 2844 Coins (多重背包)
    HDU 2602 Bone Collector(01背包)
    HDU 1171 Big Event in HDU(01背包)
    HDU 2571 命运 (入门dp)
    HDU 1069 Monkey and Banana(最长递减子序列)
    HDU 1160 FatMouse's Speed (最长上升子序列)
    HDU 2594 KMP
    POJ 3783 Balls --扔鸡蛋问题 经典DP
  • 原文地址:https://www.cnblogs.com/Gloid/p/9658421.html
Copyright © 2020-2023  润新知