您的位置:首页 > 其它

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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: