题目: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 ",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 }