hdu 5861Road(2016 Multi-University Training Contest 10——线段树+扫描线)
来源:互联网 发布:用友软件电话 编辑:程序博客网 时间:2024/05/14 04:07
题目链接:http://acm.split.hdu.edu.cn/showproblem.php?pid=5861
Road
Time Limit: 12000/6000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 661 Accepted Submission(s): 184
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 villageai 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.)
We know the transport plan in the next m days, each day there is one cargo need to transport from village
(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 31 2 31 33 42 4
Sample Output
355
Author
BUPT
Source
2016 Multi-University Training Contest 10
有n个村子,n-1条路。每条路开放一天的价格是w[i],有m天的操作,每天需要用到村子a[i]到b[i]之间的道路。
每条路只能开放或者关闭一次(不能重复开关)要确保每一个运输都要完成,求每天最小的花费。
解题思路:
每段路只能打开一次,关闭一次,我们可以求出第i 段路最早什么时候使用是s[i].day,最晚什么时候使用ss[i].day,那么我们就可以在天数s[i].day 打开它,ss[i].day+1关闭它。
遍历m 天,对于每一天,进行完打开和关闭操作后,输出总和就好。
得到第i段开始和结束在哪一天之后,要求出每一天的花费,我们就采用扫描线的方法,在开始的那天+w[i],结束的那天的后一天减w[i]。接着不断地后面加上前面的即可得到每段的花费。
详见代码。
#include <iostream>#include <cstdio>#include <cstring>using namespace std;#define N (200000+10)struct node{ int l,r,day; int flag;//用来标记能不能更新} s[N*4];struct node1{ int l,r,day; int flag;} ss[N*4];int w[N],a[N],b[N],st[N],ed[N],ans[N];void InitTree(int l,int r,int k){ s[k].l=l; s[k].r=r; s[k].day=0; s[k].flag=0; ss[k].l=l; ss[k].r=r; ss[k].day=0; ss[k].flag=0; if (l==r) return ; int mid=(l+r)/2; InitTree(l,mid,2*k); InitTree(mid+1,r,2*k+1);}void UpdataTree(int l,int r,int k,int d){ if (s[k].day) return; if (s[k].l==l&&s[k].r==r&&s[k].flag==0) { s[k].day=d;//第一次用这条路是哪一天 s[k].flag=1; return ; } if (s[k].l==s[k].r) return ; int mid=(s[k].l+s[k].r)/2; if (r<=mid) UpdataTree(l,r,2*k,d); else if (l>mid) UpdataTree(l,r,2*k+1,d); else { UpdataTree(l,mid,2*k,d); UpdataTree(mid+1,r,2*k+1,d); } s[k].flag=s[2*k].flag|s[2*k+1].flag;}void UpdataTree1(int l,int r,int k,int d){ if (ss[k].day) return; if (ss[k].l==l&&ss[k].r==r&&ss[k].flag==0) { ss[k].day=d;//最后一次用这条路是哪一天 ss[k].flag=1; return ; } if (ss[k].l==ss[k].r) return ; int mid=(ss[k].l+ss[k].r)/2; if (r<=mid) UpdataTree1(l,r,2*k,d); else if (l>mid) UpdataTree1(l,r,2*k+1,d); else { UpdataTree1(l,mid,2*k,d); UpdataTree1(mid+1,r,2*k+1,d); } ss[k].flag=ss[2*k].flag|ss[2*k+1].flag;}int SearchTree(int l,int r,int k){ if (s[k].day) return s[k].day; if (s[k].l==l&&s[k].r==r) return s[k].day; int mid=(s[k].l+s[k].r)/2; if (r<=mid) SearchTree(l,r,2*k); else if (l>mid) SearchTree(l,r,2*k+1); else { SearchTree(l,mid,2*k); SearchTree(mid+1,r,2*k+1); }}int SearchTree1(int l,int r,int k){ if (ss[k].day) return ss[k].day; if (ss[k].l==l&&ss[k].r==r) return ss[k].day; int mid=(ss[k].l+ss[k].r)/2; if (r<=mid) SearchTree1(l,r,2*k); else if (l>mid) SearchTree1(l,r,2*k+1); else { SearchTree1(l,mid,2*k); SearchTree1(mid+1,r,2*k+1); }}int main(){ int n,m; while (~scanf("%d%d",&n,&m)) { for (int i=1; i<n; i++) { scanf("%d",&w[i]); } InitTree(1,n-1,1); for (int i=1; i<=m; i++) { scanf("%d%d",&a[i],&b[i]); if (a[i]>b[i]) swap(a[i],b[i]); UpdataTree(a[i],b[i]-1,1,i); } for (int i=1; i<n; i++) st[i]=SearchTree(i,i,1); for (int i=m; i>=1; i--) { UpdataTree1(a[i],b[i]-1,1,i); } for (int i=1; i<n; i++) ed[i]=SearchTree1(i,i,1); //现在已知第i段的开始和结束分别在哪一天,求每一天需要花多少钱 //扫描线的方法 //for (int i=1; i<n; i++) // cout<<i<<" "<<st[i]<<" "<<ed[i]<<endl; memset(ans,0,sizeof(ans)); for (int i=1; i<n; i++) { ans[st[i]]+=w[i]; ans[ed[i]+1]-=w[i]; } for (int i=1; i<=m; i++) { ans[i]+=ans[i-1]; printf ("%d\n",ans[i]); } } return 0;}
0 0
- hdu 5861Road(2016 Multi-University Training Contest 10——线段树+扫描线)
- HDU 5861 Road (线段树) 2016 Multi-University Training Contest 10
- 2016 Multi-University Training Contest 10 [HDU 5861] Road (线段树区间更新+差分数组)
- hdu 5726 GCD(2016 Multi-University Training Contest 1线段树)
- hdu 5802 Windows 10(2016 Multi-University Training Contest 6——贪心+dfs)
- hdu 5858 Hard problem(2016 Multi-University Training Contest 10——数学题)
- hdu 5867 Water problem(2016 Multi-University Training Contest 10——水题)
- hdu 5860 Death Sequence(2016 Multi-University Training Contest 10——递推)
- hdu 4973 A simple simulation problem 线段树 2014 Multi-University Training Contest 10-1003
- hdu 6070 Dirt Ratio(二分+线段树)(2017 Multi-University Training Contest
- hdu 5723 Abandoned country(2016 Multi-University Training Contest 1——最小生成树+深搜)
- hdu 5733 tetrahedron(2016 Multi-University Training Contest 1——几何公式题)
- hdu 5745 La Vie en rose(2016 Multi-University Training Contest 2——暴力)
- hdu 5752 Sqrt Bo(2016 Multi-University Training Contest 3——水题)
- hdu 5753 Permutation Bo(2016 Multi-University Training Contest 3——组合)
- HDU 5755 Gambler Bo(高斯消元裸题)——2016 Multi-University Training Contest 3
- hdu 5763 Another Meaning(2016 Multi-University Training Contest 4——dp+kmp)
- hdu 5775 Bubble Sort(2016 Multi-University Training Contest 4——树状数组)
- colorhighlighter使用(sublime text3)
- Spring学习(四)
- Libev官方在线API 网址
- leetcode Jump Game
- FZU 2216 The Longest Straight (二分)
- hdu 5861Road(2016 Multi-University Training Contest 10——线段树+扫描线)
- 变频无线发射机系统电路设计详解
- UVAlive 6622 Absurdistan Roads(最小生成树+LCA)
- JavaWeb 分页
- 【软件工程】--需求分析
- 直方图均衡化
- Ubuntu快速安装jdk 1.8
- js代码执行C#代码
- jvm面试题(三)