zoukankan      html  css  js  c++  java
  • CF786B Legacy(线段树优化建图)

    传送门

    ovo这题该怎么做呢?我们首先考虑暴力建图,但是因为建图的操作太多直接就会MLE,所以这个就别想了……

    我们考虑如何优化建图。因为发现一个点可以向一个区间连边,一个区间也可以向一个点连边,想到区间很容易想到线段树……所以我们可以使用一个点来代替一段区间进行建图。

    具体的操作可以这样,我们建立两棵线段树,一棵用于存所有的出边(就是区间向点连边),每个点向其父亲建一条边权为0的边,另一棵用于存所有的入边(就是点向区间连边),每个点向其儿子建一条边权为0的边。然后对于线段树的每个叶子节点,与其编号对应的点连边。对于普通的点就直接在两点之间连边,否则的话,在不同的线段树上像区间修改一样连边即可。

    最后直接从源点开始跑一边dij就可以了。话说这种题真是神奇……以前从未见过orz

    记住这个题建图别建反了……还有就是极大值要开到longlong。

    看一下代码。

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<algorithm>
    #include<queue>
    #include<cstring>
    #include<set>
    #define rep(i,a,n) for(int i = a;i <= n;i++)
    #define per(i,n,a) for(int i = n;i >= a;i--)
    #define enter putchar('
    ')
    using namespace std;
    typedef long long ll;
    #define pr pair<ll,int>
    #define mp make_pair
    #define fi first
    #define sc second
    const int M = 1000005;
    const int N = 10000005;
     
    int read()
    {
        int ans = 0,op = 1;
        char ch = getchar();
        while(ch < '0' || ch > '9')
        {
        if(ch == '-') op = -1;
        ch = getchar();
        }
        while(ch >='0' && ch <= '9')
        {
        ans *= 10;
        ans += ch - '0';
        ch = getchar();
        }
        return ans * op;
    }
    
    struct edge
    {
        int next,to,v,from;
    }e[M<<3];
    
    int n,Q,s,cur,ecnt,head[M],lc[M],rc[M],root1,root2;
    ll dis[M],INF;
    
    set <pr> q;
    set <pr> :: iterator it;
    void add(int x,int y,int z)
    {
        e[++ecnt].to = y;
        e[ecnt].v = z;
        e[ecnt].next = head[x];
        head[x] = ecnt;
    }
    
    void build1(int &p,int l,int r)//为了避免一些不必要的麻烦……我们选择记录左右儿子动态开点(直接左右移可能会有点小问题……也可能没有)
    {
        if(l == r)
        {
        p = l;
        return;
        }
        p = ++cur;
        int mid = (l+r) >> 1;
        build1(lc[p],l,mid);
        build1(rc[p],mid+1,r);
        add(p,lc[p],0);
        add(p,rc[p],0);
    }
    
    void build2(int &p,int l,int r)
    {
        if(l == r)
        {
        p = l;
        return;
        }
        p = ++cur;
        int mid = (l+r) >> 1;
        build2(lc[p],l,mid);
        build2(rc[p],mid+1,r);
        add(lc[p],p,0);
        add(rc[p],p,0);
    }
    
    void modify(int p,int l,int r,int u,int kl,int kr,int val,int flag)//像区间修改一样进行连边
    {
        if(l == kl && r == kr)
        {
        if(flag == 2) add(u,p,val);
        else add(p,u,val);
        return;
        }
        int mid = (l+r) >> 1;
        if(kr <= mid) modify(lc[p],l,mid,u,kl,kr,val,flag);
        else if(kl > mid) modify(rc[p],mid+1,r,u,kl,kr,val,flag);
        else modify(lc[p],l,mid,u,kl,mid,val,flag),modify(rc[p],mid+1,r,u,mid+1,kr,val,flag);
        }
     /*void modify(int p,int l,int r,int u,int kl,int kr,int val,int flag)
    {
        if(kl <= l && r <= kr)
        {
        flag == 2 ? add(u,p,val) : add(p,u,val);
        return;
        }
        int mid = (l+r) >> 1;
        if(kl <= mid) modify(lc[p],l,mid,u,kl,kr,val,flag);
        if(mid < kr) modify(rc[p],mid+1,r,u,kl,kr,val,flag);
        }*/
    
    void dij(int s)
    {
        memset(dis,0x3f,sizeof(dis));
        INF = dis[s];
        dis[s] = 0,q.insert(mp(dis[s],s));
        while(!q.empty())
        {
        pr k = *(q.begin());
        q.erase(q.begin());
        for(int i = head[k.sc];i;i = e[i].next)
        {
            if(dis[e[i].to] > dis[k.sc] + e[i].v)
            {
            it = q.find(mp(dis[e[i].to],e[i].to));
            if(it != q.end()) q.erase(it);
            dis[e[i].to] = dis[k.sc] + e[i].v;
            q.insert(mp(dis[e[i].to],e[i].to));
            }
        }
        }
    }
    int main()
    {
        n = read(),Q = read(),s = read();
        cur = n;
        build1(root1,1,n);
        build2(root2,1,n);
        rep(i,1,Q)
        {
        int op = read();
        if(op == 1)
        {
            int x = read(),y = read(),z = read();
            add(x,y,z);
        }
        if(op == 2)
        {
            int x = read(),l = read(),r = read(),z = read();
            modify(root1,1,n,x,l,r,z,op);
        }
        if(op == 3)
        {
            int x = read(),l = read(),r = read(),z = read();
            modify(root2,1,n,x,l,r,z,op);
        }
        }
        //rep(i,1,ecnt) printf("%d %d %d
    ",e[i].from,e[i].to,e[i].v);
        dij(s);
        rep(i,1,n) dis[i] < INF ? printf("%I64d ",dis[i]) : printf("-1 ");
        return 0;
    }
  • 相关阅读:
    POJ:1703-Find them, Catch them(并查集好题)(种类并查集)
    POJ:2236-Wireless Network
    POJ:2010-Moo University
    POJ :3614-Sunscreen
    POJ:2395-Out of Hay
    Aizu:2224-Save your cats
    POJ:2377-Bad Cowtractors
    CSS属性大全
    博客园背景设置CSS代码
    W3C标准以及规范
  • 原文地址:https://www.cnblogs.com/captain1/p/9671174.html
Copyright © 2011-2022 走看看