#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\n";
#else
    const char LL[]="%lld\n";
#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\n",ans[i]);
    return 0;
}

原文地址:https://www.cnblogs.com/Gloid/p/9658421.html

时间: 2024-08-29 08:09:11

#41 最短路(分治+线性基)的相关文章

[BZOJ4568][SCOI2016]幸运数字(倍增LCA,点分治+线性基)

4568: [Scoi2016]幸运数字 Time Limit: 60 Sec  Memory Limit: 256 MBSubmit: 2131  Solved: 865[Submit][Status][Discuss] Description A 国共有 n 座城市,这些城市由 n-1 条道路相连,使得任意两座城市可以互达,且路径唯一.每座城市都有一个 幸运数字,以纪念碑的形式矗立在这座城市的正中心,作为城市的象征.一些旅行者希望游览 A 国.旅行者计划 乘飞机降落在 x 号城市,沿着 x

【线段树分治 线性基】luoguP3733 [HAOI2017]八纵八横

不知道为什么bzoj没有HAOI2017 题目描述 Anihc国有n个城市,这n个城市从1~n编号,1号城市为首都.城市间初始时有m条高速公路,每条高速公路都有一个非负整数的经济影响因子,每条高速公路的两端都是城市(可能两端是同一个城市),保证任意两个城市都可以通过高速公路互达. 国正在筹划“八纵八横”的高铁建设计划,计划要修建一些高速铁路,每条高速铁路两端也都是城市(可能两端是同一个城市),也都有一个非负整数的经济影响因子.国家还计划在“八纵八横”计划建成之后,将“一带一路”扩展为“一带_路一

HAOI2017 八纵八横——线段树分治+线性基

题目大意 给定一个图,每次加一些边,或者删掉一些后来加上去的边,定义一个环的价值为环上所有的边的异或和,重复走的边重复算.每次询问这个时刻图中的所有经过1号点的环的最大价值. 思路 首先考虑对于一个静态的图如何求解图中所有经过1号点的环的最大价值,发现这个经过1号点就是唬人的,图中任意一个环都可以经过1号点再走回来. 于是题目变成了求解图中环的最大价值,可以将图中所有的简单环给拎出来放到线性基里面求最大价值,不难发现这是对的. 然后题目转化为了如何求图中所有的简单环,一般我们可以直接对图dfs找

Codeforces 938G 线段树分治 线性基 可撤销并查集

Codeforces 938G Shortest Path Queries 一张连通图,三种操作 1.给x和y之间加上边权为d的边,保证不会产生重边 2.删除x和y之间的边,保证此边之前存在 3.询问x到y的路径异或最小值 保证图在任意时刻连通 首先连通图路径异或相当于从x到y的任意一条路径再异或上若干个环得到的,只要在dfs过程中把非树边成的环丢到线性基里就好了,其他环一定可以通过这些环异或组合出来 有加边删边操作怎么做呢?线段树时间分治!注意到不能保证在线段树的任意一个节点图是连通的,需要用

【BZOJ-4568】幸运数字 树链剖分 + 线性基合并

4568: [Scoi2016]幸运数字 Time Limit: 60 Sec  Memory Limit: 256 MBSubmit: 238  Solved: 113[Submit][Status][Discuss] Description A 国共有 n 座城市,这些城市由 n-1 条道路相连,使得任意两座城市可以互达,且路径唯一.每座城市都有一个幸运数字,以纪念碑的形式矗立在这座城市的正中心,作为城市的象征.一些旅行者希望游览 A 国.旅行者计划乘飞机降落在 x 号城市,沿着 x 号城市

【CF1100F】Ivan and Burgers(线性基,分治)

题意:给定n个数,每个数为c[i],有q个询问,每次询问从第l个到第r个数字的最大xor和 n,q<=5e5,c[i]<=1e6,时限3s 思路:直接线段树维护区间线性基是3个log 做法1:因为不是强制在线把询问分治能降到2个log 1 #include<bits/stdc++.h> 2 #include<cstdio> 3 #include<cstring> 4 #include<string> 5 #include<cmath>

loj#2312. 「HAOI2017」八纵八横(线性基 线段树分治)

题意 题目链接 Sol 线性基+线段树分治板子题.. 调起来有点自闭.. #include<bits/stdc++.h> #define fi first #define se second #define pb push_back #define bit bitset<B + 1> using namespace std; const int MAXN = 501, B = 1001, SS = 4001; inline int read() { char c = getchar

[BZOJ3569]DZY Loves Chinese II(随机化+线性基)

3569: DZY Loves Chinese II Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 1515  Solved: 569[Submit][Status][Discuss] Description 神校XJ之学霸兮,Dzy皇考曰JC. 摄提贞于孟陬兮,惟庚寅Dzy以降. 纷Dzy既有此内美兮,又重之以修能. 遂降临于OI界,欲以神力而凌♂辱众生. 今Dzy有一魞歄图,其上有N座祭坛,又有M条膴蠁边. 时而Dzy狂WA而怒发冲冠,神力外溢,

「专题总结」线性基

为什么要把毫无关联的线性基和群论放在一个专题里呢..? 因为它们都很毒瘤 线性基本身还是比较简单的,用于处理一些数子集异或和的集合有哪些. 然而它的考察方法总是很神奇... 题目难度大致升序,但是没有前置知识关系: 元素: $Description:$ 相传,在远古时期,位于西方大陆的 Magic Land 上,人们已经掌握了用魔法矿石炼制法杖的技术.那时人们就认识到,一个法杖的法力取决于使用的矿石. 一般地,矿石越多则法力越强,但物极必反:有时,人们为了获取更强的法力而使用了很多矿石,却在炼制