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(1≤ai,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(‘\n‘);
}

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;
}

  

时间: 2024-08-10 14:58:57

hdu-5861 Road(并查集)的相关文章

hdu 1598 find the most comfortable road (并查集 + 枚举)

题目: 链接:点击打开链接 思路: 对边排序,再枚举每条边,如果出现通路(findset(x) == findset(y))就结束. 代码: #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace std; #define MAXN 220 #define MAXM 1010 #define MAX 100000000 stru

HDU 1598 find the most comfortable road (并查集||最短路)

find the most comfortable road Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 3720    Accepted Submission(s): 1583 Problem Description XX星有许多城市,城市之间通过一种奇怪的高速公路SARS(Super Air Roam Structure---超级

Hdu 2473(并查集删除操作) Junk-Mail Filter

有木有很吊 加强 加强版   啊  ,看了都不敢做了   ,后来先做了食物链这个我还是看过的,但还是A不掉,没明白神魔意思 ,总而言之,大牛的博客是个好东西,我就那么看了一下,还是不懂怎莫办啊,哎,就那样就A掉了....... 今天我们来谈一下这个并查集的删除操作,根据我对大牛的理解啊,这个并查集的删除操作并不是把原来的节点删除掉,而是用一个替身替掉,现在的这个点只是用作桥梁的作用,即是无用的,del  ,,,del  ,,,,删除,那些被删掉的就从n开始给他们一个地址,然后即如下代码所示 #i

HDU 4496 D-City(并查集,逆思维)

题目 熟能生巧...常做这类题,就不会忘记他的思路了... //可以反过来用并查集,还是逐个加边,但是反过来输出...我是白痴.....又没想到 //G++能过,C++却wa,这个也好奇怪呀... #include<stdio.h> #include<string.h> int fx,fy,r,bin[10010]; int x[100010],y[100010],n,m,i,count,ans[100010],j; int find(int x) { //改成这样就不会超时了么好

hdu1598find the most comfortable road(并查集+枚举,求起点到终点的边中最大边减最小边差值最小)

Problem Description XX星有许多城市,城市之间通过一种奇怪的高速公路SARS(Super Air Roam Structure---超级空中漫游结构)进行交流,每条SARS都对行驶在上面的Flycar限制了固定的Speed,同时XX星人对 Flycar的"舒适度"有特殊要求,即乘坐过程中最高速度与最低速度的差越小乘坐越舒服 ,(理解为SARS的限速要求,flycar必须瞬间提速/降速,痛苦呀 ), 但XX星人对时间却没那么多要求.要你找出一条城市间的最舒适的路径.(

HDU 1272 简单并查集

小希的迷宫 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 24915    Accepted Submission(s): 7641 Problem Description 上次Gardon的迷宫城堡小希玩了很久(见Problem B),现在她也想设计一个迷宫让Gardon来走.但是她设计迷宫的思路不一样,首先她认为所有的通道都应该是双

hdu 5861 Road 两棵线段树

传送门:hdu 5861 Road 题意: 水平线上n个村子间有 n-1 条路. 每条路开放一天的价格为 Wi 有 m 天的操作,每天需要用到村子 Ai~Bi 间的道路 每条路只能开放或关闭一次. (不能重复开关) 求每天的最小花费. 思路: 第一次线段树:维护每条路第一次和最后一次被用到的天数.以下代码维护了 mn:第一次被用到,mx:最后一次被用到,lazy:被更新的最大值若当前区间被lazy维护而没有更新到点,那么这个子节点的最小值就可能被改变.所以我这里的子节点更新是根据父节点的最大和最

hdu 3038 (并查集)

题目大意: 给出m个询问,问[l,r]之间的和   ,求出有多少次询问不和之前的矛盾的. 思路分析: 用并查集记录当前节点到根节点的和. #include <cstdio> #include <iostream> #include <cstring> #include <algorithm> #define maxn 222222 using namespace std; int set[maxn]; int sum[maxn]; int find(int

hdu 4496 D-City 并查集

D-City Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65535/65535 K (Java/Others) Total Submission(s): 2317    Accepted Submission(s): 814 Problem Description Luxer is a really bad guy. He destroys everything he met. One day Luxer went to D-