zoukankan      html  css  js  c++  java
  • hdu-5861 Road(并查集)

    题目链接:

    Road

    Time Limit: 12000/6000 MS (Java/Others)   

     Memory Limit: 65536/65536 K (Java/Others)



    Problem Description
    There are n villages along a high way, and divided the high way into n-1 segments. Each segment would charge a certain amount of money for being open for one day, and you can open or close an arbitrary segment in an arbitrary day, but you can open or close the segment for just one time, because the workers would be angry if you told them to work multiple period.

    We know the transport plan in the next m days, each day there is one cargo need to transport from village ai to village bi, and you need to guarantee that the segments between ai and bi are open in the i-th day. Your boss wants to minimize the total cost of the next m days, and you need to tell him the charge for each day.

    (At the beginning, all the segments are closed.)
     
    Input
    Multiple test case. For each test case, begins with two integers n, m(1<=n,m<=200000), next line contains n-1 integers. The i-th integer wi(1<=wi<=1000) indicates the charge for the segment between village i and village i+1 being open for one day. Next m lines, each line contains two integers ai,bi(1ai,bi<=n,ai!=bi).
     
    Output
    For each test case, output m lines, each line contains the charge for the i-th day.
     
    Sample Input
    4 3
    1 2 3
    1 3
    3 4
    2 4
     
    Sample Output
    3
    5
    5
     
    题意:
     
    问那个点中间n-1个线段,每个线段只能开关一次,m天,每天要从ai到bi,要求这中间的线段都是开着的;现在问每天的最少花费是多少;
     
    思路:
     
    可以发现,每个线段在它第一次和最后一次被覆盖这期间都需要打开;所以需要找到每个线段的开始和结束时间
    用并查集p[i]表示[i,~的第一个还没有被覆盖的位置;然后1~m和m~1个扫一遍可以找到开始和结束时间;
    然后对于第i天,先加上这一天需要打开的线段,和就是这天的答案,然后再减去这一天需要关闭的线段;
     
    AC代码:
    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    #include <bits/stdc++.h>
    #include <stack>
    #include <map>
     
    using namespace std;
     
    #define For(i,j,n) for(int i=j;i<=n;i++)
    #define mst(ss,b) memset(ss,b,sizeof(ss));
     
    typedef  long long LL;
     
    template<class T> void read(T&num) {
        char CH; bool F=false;
        for(CH=getchar();CH<'0'||CH>'9';F= CH=='-',CH=getchar());
        for(num=0;CH>='0'&&CH<='9';num=num*10+CH-'0',CH=getchar());
        F && (num=-num);
    }
    int stk[70], tp;
    template<class T> inline void print(T p) {
        if(!p) { puts("0"); return; }
        while(p) stk[++ tp] = p%10, p/=10;
        while(tp) putchar(stk[tp--] + '0');
        putchar('
    ');
    }
     
    const LL mod=1e9+7;
    const double PI=acos(-1.0);
    const int inf=1e9;
    const int N=2e5+20;
    const int maxn=1e4+220;
    const double eps=1e-12;
    
    int n,m,w[N],a[N],b[N],p[N];
    int x,y;
    vector<int>st[N],en[N];
    int findset(int x)
    {
        if(x==p[x])return x;
        return p[x]=findset(p[x]);
    }
    int same(int x,int y)
    {
        int fx=findset(x),fy=findset(y);
        if(fx>fy)p[fy]=fx;
        else if(fx<fy)p[fx]=fy;
    }
    int main()
    {
       while(scanf("%d%d",&n,&m)!=EOF)
       {
            For(i,1,n-1)read(w[i]);
            int high=max(n,m)+10;
            for(int i=0;i<=high;i++)
            {
                p[i]=i;
                st[i].clear();
                en[i].clear();
            }
            For(i,1,m)
            {
                read(a[i]);read(b[i]);
                if(a[i]>b[i])swap(a[i],b[i]);
                int r=a[i];
                while(1)
                {
                    r=findset(r);
                   if(r>=b[i])break;
                   same(r,r+1);
                   st[i].push_back(r);
                }
            }
            for(int i=0;i<=high;i++)p[i]=i;
            for(int i=m;i>0;i--)//找到第i天要关闭的线段
            {
                int r=a[i];
                while(1)
                {
                    r=findset(r);
                    if(r>=b[i])break;
                    same(r,r+1);
                    en[i].push_back(r);
                }
            }
            int ans=0;
            for(int i=1;i<=m;i++)
            {
                int len=st[i].size();
                for(int j=0;j<len;j++)//加上这一天要打开的线段
                {
                    int x=st[i][j];
                    ans+=w[x];
                }
                print(ans);
                len=en[i].size();
                for(int j=0;j<len;j++)//关闭这天需要关闭的线段;
                {
                    int x=en[i][j];
                    ans-=w[x];
                }
            }
       }
        return 0;
    }
    

      

  • 相关阅读:
    Pytorch安装
    使用Inception-v3进行图像分类
    Tensorflow模型保存与载入
    LSTM用于MNIST手写数字图片分类
    卷积神经网络应用于MNIST数据集分类
    手工设计神经MNIST使分类精度达到98%以上
    关于优化器的选择
    手动设计神经网络进行MNIST分类
    Matplotlib学习
    Apiview使用方法
  • 原文地址:https://www.cnblogs.com/zhangchengc919/p/5785910.html
Copyright © 2011-2022 走看看