Road

题目链接:

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

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

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

Source


2016 Multi-University Training Contest 10


##题意:

水平线上n个村子间有 n-1 条路. 每条路开放一天的价格为 Cost_i.
有 m 天的操作,每天需要用到村子 Ai~Bi 间的道路.
每条路只能开放或关闭一次. (不能重复开关)
求每天的最小花费.


##题解:

用了两次线段树维护,写得很丑,还不如写两次线段树.
第一次线段树:
维护每条路第一次和最后一次被用到的天数.
以下代码维护了 mi:第一天,ma:最后一天,has:是否已经被用过.
mi和ma分别是子节点的最小值和最大值,关键是 has 的维护. (一开始没有写has, WA了)
has表示当前区间的结点是否都已经被用过.(即有mi值). 如果has=1那么就可以直接用lazy维护区间中所有结点的最大值.
若has=0意味着某个子节点还没有被用过, 若当前区间被lazy维护而没有更新到点,那么这个子节点的最小值就可能被改变.
这个地方关于维护的对象和lazy的处理做的不是很好,不过幸好过了. 晚点再改一下代码.
第二次线段树:
维护每天用了多少钱.
根据以上结果维护,对于每条路(被用到过的)区间更新第一次到最后一次这些天用的钱.


##代码:
``` cpp
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define LL long long
#define eps 1e-8
#define maxn 201000
#define mod 100000007
#define inf 0x3f3f3f3f
#define mid(a,b) ((a+b)>>1)
#define IN freopen("in.txt","r",stdin);
using namespace std;

int n,m;

LL cost[maxn];

struct Tree

{

int left,right;

LL lazy,mi,ma,sum;

bool has;

}tree[maxn<<2];

bool flag;

void pushup(int i) {

tree[i].mi = min(tree[i<<1].mi, tree[i<<1|1].mi);

tree[i].ma = max(tree[i<<1].ma, tree[i<<1|1].ma);

tree[i].has = tree[i<<1].has && tree[i<<1|1].has;

if(flag) tree[i].sum = (tree[i<<1].sum + tree[i<<1|1].sum);

}

/递归建树/

void build(int i,int left,int right)

{

tree[i].left=left;

tree[i].right=right;

tree[i].lazy=0;

if(left==right){
tree[i].mi=inf;
tree[i].ma=-inf;
tree[i].has = 0;
tree[i].sum = 0;
return ;
} int mid=mid(left,right); build(i<<1,left,mid);
build(i<<1|1,mid+1,right); pushup(i);

}

/区间修改,标记下传:每当访问到当前结点的子节点时,下传标记/

void pushdown(int i)

{

if(tree[i].lazy){

if(flag) {

tree[i<<1].lazy+=tree[i].lazy;

tree[i<<1|1].lazy+=tree[i].lazy;

tree[i<<1].sum+=(tree[i<<1].right-tree[i<<1].left+1)tree[i].lazy;

tree[i<<1|1].sum+=(tree[i<<1|1].right-tree[i<<1|1].left+1)
tree[i].lazy;

tree[i].lazy=0; /下传后清零/

} else {

tree[i<<1].lazy=tree[i].lazy;

tree[i<<1|1].lazy=tree[i].lazy;

//tree[i<<1].mi = min(tree[i].lazy, tree[i<<1].mi);

//tree[i<<1|1].mi = min(tree[i].lazy, tree[i<<1|1].mi);

tree[i<<1].ma = max(tree[i].lazy, tree[i<<1].ma);

tree[i<<1|1].ma = max(tree[i].lazy, tree[i<<1|1].ma);

tree[i].lazy=0; /下传后清零/

}

}

}

/区间修改,d为改变量/

void update(int i,int left,int right,LL d)

{

if(tree[i].leftleft&&tree[i].rightright)

{

tree[i].mi = min(d, tree[i].mi);

tree[i].ma = max(d, tree[i].ma);

if(flag) {

tree[i].sum += (right-left+1) * d;

tree[i].lazy += d;

return;

} else {

if(tree[i].has) {

tree[i].lazy = d;

return;

}

if(tree[i].left==tree[i].right) {

if(!tree[i].has) tree[i].mi = tree[i].ma = d;

tree[i].has = 1;

return ;

}

}

}

pushdown(i);

int mid=mid(tree[i].left,tree[i].right);

if(right<=mid) update(i<<1,left,right,d);
else if(left>mid) update(i<<1|1,left,right,d);
else
{
update(i<<1,left,mid,d);
update(i<<1|1,mid+1,right,d);
} pushup(i);

}

/区间结果查询/

typedef pair<LL,LL> pii;

pii query(int i,int left,int right)

{

if(tree[i].leftleft&&tree[i].rightright)

return make_pair(tree[i].mi,tree[i].ma);

pushdown(i);

int mid=mid(tree[i].left,tree[i].right);

if(right<=mid) return query(i<<1,left,right);
else if(left>mid) return query(i<<1|1,left,right);
//else return 0;

}

LL query_sum(int i,int left,int right)

{

if(tree[i].leftleft&&tree[i].rightright)

return tree[i].sum;

pushdown(i);

int mid=mid(tree[i].left,tree[i].right);

if(right<=mid) return query_sum(i<<1,left,right);
else if(left>mid) return query_sum(i<<1|1,left,right);
else return query_sum(i<<1,left,mid)+query_sum(i<<1|1,mid+1,right);

}

int starts[maxn], endss[maxn];

int main(int argc, char const *argv[])

{

//IN;

//int t; cin >> t;
while(scanf("%d %d", &n, &m) != EOF)
{
flag = 0;
for(int i=1; i<=n-1; i++)
scanf("%lld", &cost[i]);
build(1, 1, n-1);
for(int i=1; i<=m; i++) {
int x,y; scanf("%d %d", &x,&y);
if(x > y) swap(x, y);
update(1, x, y-1, i);
} for(int i=1; i<=n-1; i++) {
pii tmp = query(1, i, i);
starts[i] = tmp.first;
endss[i] = tmp.second;
} flag = 1;
build(1, 1, m);
for(int i=1; i<=n-1; i++) {
if(starts[i] == inf) continue;
update(1, starts[i], endss[i], cost[i]);
} for(int i=1; i<=m; i++) {
printf("%lld\n", query_sum(1,i,i));
}
} return 0;

}

HDU 5861 Road (线段树)的更多相关文章

  1. HDU 5861 Road 线段树区间更新单点查询

    题目链接: http://acm.split.hdu.edu.cn/showproblem.php?pid=5861 Road Time Limit: 12000/6000 MS (Java/Othe ...

  2. hdu 5861 Road 两棵线段树

    传送门:hdu 5861 Road 题意: 水平线上n个村子间有 n-1 条路. 每条路开放一天的价格为 Wi 有 m 天的操作,每天需要用到村子 Ai~Bi 间的道路 每条路只能开放或关闭一次. ( ...

  3. hdu 4031 attack 线段树区间更新

    Attack Time Limit: 5000/3000 MS (Java/Others)    Memory Limit: 65768/65768 K (Java/Others)Total Subm ...

  4. hdu 4288 离线线段树+间隔求和

    Coder Time Limit: 20000/10000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Su ...

  5. hdu 3016 dp+线段树

    Man Down Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total S ...

  6. 2016 Multi-University Training Contest 10 [HDU 5861] Road (线段树:区间覆盖+单点最大小)

    HDU 5861 题意 在n个村庄之间存在n-1段路,令某段路开放一天需要交纳wi的费用,但是每段路只能开放一次,一旦关闭将不再开放.现在给你接下来m天内的计划,在第i天,需要对村庄ai到村庄bi的道 ...

  7. HDU 5861 Road(线段树 区间修改 单点查询)

    Road Time Limit: 12000/6000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submi ...

  8. HDU 5877 dfs+ 线段树(或+树状树组)

    1.HDU 5877  Weak Pair 2.总结:有多种做法,这里写了dfs+线段树(或+树状树组),还可用主席树或平衡树,但还不会这两个 3.思路:利用dfs遍历子节点,同时对于每个子节点au, ...

  9. HDU 3308 LCIS (线段树区间合并)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3308 题目很好懂,就是单点更新,然后求区间的最长上升子序列. 线段树区间合并问题,注意合并的条件是a[ ...

随机推荐

  1. 【温故知新】C#委托delegate

    在c#的学习过程中,学到委托与事件总会迷糊一段时间,迷糊过后自然而就似懂非懂了~,所以最近我打算把以前所学的迷糊过的知识总结,温故知新,总结记录下来. 首先,我们来看一下msdn对委托的定义: del ...

  2. datagridview的某些属性以及增删改查

    private void button1_Click(object sender, EventArgs e) //查询 { dataGridView1.AutoGenerateColumns = fa ...

  3. web开发workflow

    web development是一个创建和实施一个新的互联网展示的过程,web网站可以是个非常成熟包罗万象的网站,也可以只是一个blog或者一两个页面.如果未做好充分的准备,web开发将是一个非常复杂 ...

  4. sql DROP 和DELETE、TRUNCATE用法

    DROP:删除数据库已存在的表DROP TABLE tbname DELETE:删除记录delete from tbname truncate:清空表,重置索引truncate table tbnam ...

  5. ADO与ADO.NET的区别与介绍

    1. ADO与ADO.NET简介ADO与ADO.NET既有相似也有区别,他们都能够编写对数据库服务器中的数据进行访问和操作的应用程序,并且易于使用.高速度.低内存支出和占用磁盘空间较少,支持用于建立基 ...

  6. 连接mongo的服务提示:HTTP Status 500 - com.mongodb.MongoException$Network: can't call something

    连接mongo的服务提示以下错误 原因:达到了mongodb启动时预设的最大连接数,无法创建新的连接 HTTP Status 500 - com.mongodb.MongoException$Netw ...

  7. 一行JS代码,解决DedeCMS TAG标签错误输入符号问题

    在维护内容的时候, Tag标签输入经常要来回切换输入法,  只能通过','号分隔.  中文用户, 输入法出来的经常是全角的, 经常弄错, 增加了检查的工作量,  现在只要一句JS代码, 就自动替换所有 ...

  8. web.xml 中的listener、 filter、servlet 加载顺序

    在项目中总会遇到一些关于加载的优先级问题,近期也同样遇到过类似的,所以自己查找资料总结了下,下面有些是转载其他人的,毕竟人家写的不错,自己也就不重复造轮子了,只是略加点了自己的修饰. 首先可以肯定的是 ...

  9. 【UVa-514】铁轨——栈的学习

    UVa514 Rails(铁轨) 题目:铁轨 题目链接: UVa514链接 题目描述: 某城市有一个火车站,有n节车厢从A方向驶入车站,按进站的顺序编号为1-n.你的任务是判断是否能让它们按照某种特定 ...

  10. 中小型数据库 RMAN CATALOG 备份恢复方案(一)

    对于数据库的稳定性,高可用,跨平台以及海量数据库的处理,Oracle 数据库通常是大型数据库和大企业的首选.尽管如此,仍然不乏很多中小企业想要品尝一下Oracle腥味,因此在Oracle环境中也有不少 ...