zoukankan      html  css  js  c++  java
  • 分享二合一 第三弹

    分享二合一 第三弹

    CF938D Buy a Ticket

    题目链接:https://www.luogu.com.cn/problem/CF938D

    关于中文题意没说明是往返路这点各路神犇已经吐槽个遍了,我这就不再提了。

    首先是点权的处理,相信大家多少都有点经验了,每个点都有一场演唱会,那么搞一个超级源点,默认他是0,直接对他向每个点连边(单向,不然就乱了),边权为点权即可。

    因为之前调代码看了LZZ大佬的题解,到这里很想吐槽一句,上回LZZ大佬那个02搞得我实在记忆深刻万恶的标题党,骗我进来不说,我还不会做,(¬︿¬)

    然后是怎么处理道路的往返问题,看别的神犇说从数据范围上看出来是标准的Dij最短路,所以往跑一遍最短路的方向上去靠,那么结合原题中给的表达式,稍微模拟一下就能得出建边时边权乘2即可。

    然后有一个需要注意的地方,那就是我们建边时因为要把超级源点的也算进去,所以前向星存边时数组至少开三倍。我是搞不明白为什么数组开小了vjudge上会报WA,搞得我调了一早上...

    #include <cstdio>
    #include <queue>
    #include <algorithm>
    #include <iostream>
    #include <vector>
    #include <cstring>
    #define ll long long 
    #define Game return 
    #define Over 0
    using namespace std;
    const int maxn = 200000+10, maxm = 400000+10;
    
    int head[maxn], len = 0;
    
    struct Edge{
        int to,nex;
        ll w;
    }e[maxm << 1];//这里要开三倍maxn...
    
    void Add(int u,int v,ll w){
        e[++len].to = v;
        e[len].nex = head[u];
        e[len].w = w;
        head[u] = len;
    }
    
    ll dis[maxn], n, m;
    bool vis[maxn];
    
    struct Node{
        ll num, val;
        Node(){};
        Node(ll a,ll b){
            num = a;
            val = b;
        }
        bool operator <(const Node& x)const{
            return val > x.val;
        }
    };
    
    void Dij(){
        priority_queue <Node> q;
        for(int i = 1; i <= n; i++)
            dis[i] = 9999999999999999;
        memset(vis, 0, sizeof vis);
        dis[0] = 0;
        q.push(Node(0,0));
    
        while(!q.empty()){
            ll num = q.top().num;
            ll val = q.top().val;
            q.pop();
            if(vis[num]) continue;
            vis[num] = 1;
            for(int i = head[num]; i; i = e[i].nex){
                ll v = e[i].to, w = e[i].w;
                if(dis[v] > dis[num] + w){
                    dis[v] = dis[num] + w;
                    q.push(Node(v,dis[v]));
                }
            } 
        }
    }
    
    int main(){
        while(~scanf("%lld %lld", &n, &m)){
            for(int i = 1; i <= m; i++){
                int u,v;
                ll w;
                scanf("%d %d %lld", &u, &v, &w);
                Add(u, v, w << 1), Add(v, u, w << 1);
            }
            for(int i = 1; i <= n; i++){
                ll w;
                scanf("%lld", &w);
                Add(0, i ,w);
            }
            Dij();
            for(int i = 1; i <= n; i++)
                printf("%lld ", dis[i]);
    
            memset(head, 0, sizeof head);
            len = 0;
        }
        Game Over;
    }
    

    BZOJ5334 数学计算

    一开始真没看出来该怎么做,没有往区间那方面去想。。。看了题解才知道要用线段树,然后剩下的就是一个单点修改区间查询的板子了。。。

    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    #include <iostream>
    #include <queue>
    #include <vector>
    #include <cmath>
    using namespace std;
    #define ll long long
    #define lson u<<1
    #define rson u<<1|1
    const int maxn = 200000+10;
    
    struct Node{
        int l,r,w;    
    }tre[maxn<<2];
    
    int t,n,mod;
    
    void Build(int u,int l,int r){
        tre[u].w = 1;
        tre[u].l = l;
        tre[u].r = r;
        if(l == r) return ;
        int mid = (l + r) >> 1;
        Build(lson,l,mid);
        Build(rson,mid + 1,r);
    }
    
    void Update(int u){
        tre[u].w = 1ll * tre[lson].w * tre[rson].w %mod;
        return ;
    }
    
    void Change(int u,int x,int v){
        if(tre[u].l == tre[u].r){
            tre[u].w = v;
            return ;
        }
        int mid = (tre[u].l + tre[u].r) >> 1;
        if(x <= mid) Change(lson,x,v);
        if(x > mid) Change(rson,x,v);
        Update(u);
    }
    
    int Query(int u,int l,int r){
        if(l > r) return 1;
        if(l <= tre[u].l && r >= tre[u].r){
            return tre[u].w;
        }
        int mid = (tre[u].l + tre[u].r) >> 1;
        return 1ll * Query(lson,l,min(r,mid)) * Query(rson,max(l,mid+1),r) %mod;
    }
    
    int main(){
        cin >> t;
        for(int cnt = 1;cnt <= t;cnt++){
            scanf("%d %d",&n,&mod);
            Build(1,1,n);
            for(int i = 1;i <= n;i++){
                int flag,x;
                scanf("%d %d",&flag,&x);
                if(flag == 1) Change(1,i,x);
                else Change(1,x,1);
                printf("%d
    ",tre[1].w);
            }
        }
        return 0;
    }
    
  • 相关阅读:
    html5晋级之路-响应式布局基本实现
    html5晋级之路-css动画-过度
    html5晋级之路-css尺寸操作
    ios-晋级之路 在模拟器中测试定位
    html5晋级之路-css选择器
    html5 css定位
    ios-晋级之路 CocoaPods引用第三方库不import不自动补齐
    html5晋级之路-css背景
    02需求工程-软件建模与分析阅读笔记
    01需求工程-软件建模与分析阅读笔记
  • 原文地址:https://www.cnblogs.com/Zfio/p/12981288.html
Copyright © 2011-2022 走看看