HDU 5861 Road

题目:Road

链接:http://acm.split.hdu.edu.cn/showproblem.php?pid=5861

题意:有n 个村庄在一条公路上,每两个村庄之间的路有使用和不使用两种状态,使用时,每天需耗费wi 元,每段路初始时都是不使用的,在m 天中,我们总共可以打开一次、关闭一次,从第一天到第m 天,每一天给出ai、bi,表示ai 到bi 之间的路必须是通的,问每一天n-1段路的总耗费最小为多少。

思路:

  每段路只能打开一次,关闭一次,我们可以求出第i 段路最早什么时候使用t1,最晚什么时候使用t2,那么我们就可以在天数t1 打开它,t2+1关闭它。

  离线+线段树可以处理出每一段路的参数t1、t2。比如第i 天要使用ai 到bi,那么ai 到bi 赋值i ,维护最大值和最小值即可。

  接下来可以用vector<int> v[N];来保存第i 天要打开哪些路,再用一个保存第i 天关闭哪些路。打开路i 就是点i 赋值wi,关闭就是赋值0。

  遍历m 天,对于每一天,进行完打开和关闭操作后,输出总和就好。

AC代码:

 

  1 #include<stdio.h>
  2 #include<string.h>
  3 #include<stdlib.h>
  4 #include<math.h>
  5 #include<set>
  6 #include<map>
  7 #include<list>
  8 #include<stack>
  9 #include<queue>
 10 #include<vector>
 11 #include<string>
 12 #include<algorithm>
 13 using namespace std;
 14 #define lson rt<<1
 15 #define rson rt<<1|1
 16 #define N 200020
 17 #define M 100010
 18 #define Mod 1000000007
 19 #define LL long long
 20 #define INF 0x7fffffff
 21 #define FOR(i,f_start,f_end) for(int i=f_start;i<=f_end;i++)
 22 #define REP(i,f_end,f_start) for(int i=f_end;i>=f_start;i--)
 23 #define MEM(x,i) memset(x,i,sizeof(x))
 24 
 25 struct Node
 26 {
 27   int Max;
 28   int Min;
 29   int w;
 30   int l,r;
 31   int mid()
 32   {
 33     return (l+r)/2;
 34   }
 35 };
 36 Node v[N<<2];
 37 void build(int l,int r,int rt)
 38 {
 39   v[rt].Min=INF;
 40   v[rt].Max=0;
 41   v[rt].w=0;
 42   v[rt].l=l;
 43   v[rt].r=r;
 44   if(l==r-1) return ;
 45   build(l,v[rt].mid(),lson);
 46   build(v[rt].mid(),r,rson);
 47 }
 48 void push_day(int rt)
 49 {
 50   if(v[rt].Min!=INF)
 51   {
 52     v[lson].Min=min(v[lson].Min,v[rt].Min);
 53     v[rson].Min=min(v[rson].Min,v[rt].Min);
 54     v[rt].Min=INF;
 55   }
 56   if(v[rt].Max!=0)
 57   {
 58     v[lson].Max=max(v[lson].Max,v[rt].Max);
 59     v[rson].Max=max(v[rson].Max,v[rt].Max);
 60     v[rt].Max=0;
 61   }
 62 }
 63 void update_day(int l,int r,int g,int rt)
 64 {
 65   if(v[rt].l==l && v[rt].r==r)
 66   {
 67     v[rt].Max=max(v[rt].Max,g);
 68     v[rt].Min=min(v[rt].Min,g);
 69     return ;
 70   }
 71   push_day(rt);
 72 
 73   int mid=v[rt].mid();
 74   if(l>=mid) update_day(l,r,g,rson);
 75   else if(r<=mid) update_day(l,r,g,lson);
 76   else
 77   {
 78     update_day(l,mid,g,lson);
 79     update_day(mid,r,g,rson);
 80   }
 81 }
 82 void look_day(int x,int &Max,int &Min,int rt)
 83 {
 84   if(v[rt].l==v[rt].r-1)
 85   {
 86     Max=v[rt].Max+1;
 87     Min=v[rt].Min;
 88     return ;
 89   }
 90   push_day(rt);
 91   int mid=v[rt].mid();
 92   if(x<mid) look_day(x,Max,Min,lson);
 93   else if(x>=mid) look_day(x,Max,Min,rson);
 94 }
 95 vector<int> vv[N];
 96 vector<int> u[N];
 97 int w[N];
 98 void up(int rt)
 99 {
100   v[rt].w=v[lson].w+v[rson].w;
101 }
102 void update(int x,int w,int rt)
103 {
104   if(v[rt].l==v[rt].r-1)
105   {
106     v[rt].w=w;
107     return ;
108   }
109   int mid=v[rt].mid();
110   if(x<mid) update(x,w,lson);
111   else if(x>=mid) update(x,w,rson);
112   up(rt);
113 }
114 void update(int x,int rt)
115 {
116   if(v[rt].l==v[rt].r-1)
117   {
118     v[rt].w=0;
119     return ;
120   }
121   int mid=v[rt].mid();
122   if(x<mid) update(x,lson);
123   else if(x>=mid) update(x,rson);
124   up(rt);
125 }
126 int main()
127 {
128   int n,m,x,y;
129   while(scanf("%d%d",&n,&m)!=EOF)
130   {
131     build(1,n,1);
132 
133     FOR(i,1,n-1){
134       scanf("%d",&w[i]);
135     }
136     FOR(i,1,m){
137       scanf("%d%d",&x,&y);
138       if(x>y) x^=y^=x^=y;
139       update_day(x,y,i,1);
140     }
141     FOR(i,1,n-1){
142       int Max,Min;
143       look_day(i,Max,Min,1);
144       if(Min!=INF) vv[Min].push_back(i);
145       if(Max!=0) u[Max].push_back(i);
146     }
147 
148     FOR(i,1,m){
149       for(int j=0;j<vv[i].size();j++){
150         update(vv[i][j],w[vv[i][j] ],1);
151       }
152       for(int j=0;j<u[i].size();j++){
153         update(u[i][j],1);
154       }
155       printf("%d\n",v[1].w);
156     }
157     FOR(i,1,m+1)
158     {
159       vv[i].clear();
160       u[i].clear();
161     }
162   }
163   return 0;
164 }

 

转载于:https://www.cnblogs.com/hchlqlz-oj-mrj/p/5784865.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值