2016多校10 HDU 5861 Road
2016-08-21 22:53
411 查看
2016多校联合训练#10
HDU 5861 Road
线段树
传送门:HDU题意
线性的路上有1到n n个城市,相邻城市间有双向的路,每条路初始时是封闭的。每条路开启时每天有一个维护费用,而且每条路只能被开启以及封闭一次。现在m天里,每天需要从a地运货到b地,你需要保证每天ab之间所有路是开启的。求每天的最小花费。思路
因为每条路只能开启一次以及封闭一次,所以需要找到每条路最早使用时间以及最晚使用时间。怎么找?线段树维护区间最大值(序号最大的天,最晚使用)和最小值(同理,最早使用)。把路作为叶子节点,区间更新。求每天的最小费用,扫描线思想。一次递归的查询,把每天需要开启和关闭的路记下来,在扫一遍就行了。至于记录的方式,怎么搞都行了,我是用二维的vector,不卡时间。
最后扫的时候,用一个last变量。每到一天,减去昨天关的路,加上今天开的路,就是今天的花费。
代码
数据范围是200000。。不是100000。。#include <iostream> #include <cstdio> #include <algorithm> #include <cstdlib> #include <cstring> #include <cmath> #include <vector> #include <queue> #include <stack> #include <iomanip> #include <string> #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 using namespace std; const int MAXN=200005; const int oo=1000000007; typedef long long int LL; struct Tree{ int ma; int mi; int lazy; }sum[MAXN<<2]; int m,n; void PushUP(int rt) { sum[rt].ma=max(sum[rt<<1].ma,sum[rt<<1|1].ma); sum[rt].mi=min(sum[rt<<1].mi,sum[rt<<1|1].mi); } void build(int l,int r,int rt) { if(l==r) { sum[rt].ma=-1; sum[rt].mi=oo; sum[rt].lazy=0; return; } int m=(l+r)>>1; build(lson); build(rson); PushUP(rt); } void PushDown(int rt) { if(sum[rt].lazy) { sum[rt<<1].lazy=sum[rt<<1|1].lazy=sum[rt].lazy; sum[rt<<1].ma=max(sum[rt<<1].ma,sum[rt].ma); sum[rt<<1|1].ma=max(sum[rt<<1|1].ma,sum[rt].ma); sum[rt<<1].mi=min(sum[rt<<1].mi,sum[rt].mi); sum[rt<<1|1].mi=min(sum[rt<<1|1].mi,sum[rt].mi); sum[rt].lazy=0; } return; } void update(int L,int R,int p,int l,int r,int rt) { if(L<=l&&r<=R) { sum[rt].ma=max(sum[rt].ma,p); sum[rt].mi=min(sum[rt].mi,p); sum[rt].lazy=1; return; } PushDown(rt); int m=(l+r)>>1; if(L<=m) update(L,R,p,lson); if(R>m) update(L,R,p,rson); } vector<int> da[MAXN][2]; void query(int l,int r,int rt) { if(l==r) { if(sum[rt].ma!=-1) { int d2=sum[rt].ma; int d1=sum[rt].mi; da[d1][0].push_back(l); da[d2][1].push_back(l); } return; } PushDown(rt); int m=(r+l)>>1; query(lson); query(rson); } int a[MAXN]; int main() { while(scanf("%d%d",&n,&m)==2) { for(int i=0;i<=m+1;i++) { da[i][0].clear(); da[i][1].clear(); } memset(sum,0,sizeof(sum)); build(1,n-1,1); memset(a,0,sizeof(a)); for(int i=1;i<n;i++) scanf("%d",&a[i]); for(int i=1;i<=m;i++) { int l,r; scanf("%d%d",&l,&r); if(l>r) swap(l,r); r--; update(l,r,i,1,n-1,1); } query(1,n-1,1); int last=0; for(int i=1;i<=m;i++) { for(int j=0;j<da[i][0].size();j++) last+=a[da[i][0][j]]; printf("%d\n",last); for(int j=0;j<da[i][1].size();j++) last-=a[da[i][1][j]]; } } return 0; }
相关文章推荐
- 一个靠谱的maven仓库镜像地址
- codeforces707C:Pythagorean Triples
- 转载:Ajax及 GET、POST 区别
- BZOJ2758 : [SCOI2012]Blinker的噩梦
- Makefile 自动生成依赖
- ASP.NET缓存之数据库缓存依赖(二)
- markdown 文章标签
- Qt程序学习(三)------QTreeWidget、右键菜单、动态改变comboBox、QTreeWidgetItem的对应列的文字编辑
- Spring_Bean 之间的关系
- linux下进程权限分析
- 使用R并行方式对数值型数据离散化
- lua 的堆栈 与 C++的获取笔录
- shell常用命令 2016/8/21
- display:none与visible:hidden的区别 slideDown与
- 产品经理应该多看数据,但绝不能迷信数据
- Jvm支持的最大线程数
- xml的dom4j操作
- 引入思考的电影电视动漫
- 括号序列合法性检查
- 智能计算与应用课题组网站