2016多校训练Contest10: 1005 Road hdu5861

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 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<=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(1ai,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 3 1 2 3 1 3 3 4 2 4
 

Sample Output
  
  
3 5 5
 
维护每条路的最早使用天数和最后使用天数
这个可以用线段树来区间维护最大最小值
排序后按照使用时间扫一遍就好了
#include<map>
#include<cmath>
#include<queue>
#include<vector>
#include<cstdio>
#include<string>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
struct tree
{
	int l,r;
	int ma,mi;
	int tag1,tag2;
}tr[1600001];
inline void up(int p)
{
	if(tr[p].l==tr[p].r)
		return ;
	tr[p].ma=max(tr[p*2].ma,tr[p*2+1].ma);
	tr[p].mi=min(tr[p*2].mi,tr[p*2+1].mi);
}
inline void push(int p)
{
	if(tr[p].l==tr[p].r)
		return ;
	tr[p*2].ma=max(tr[p].tag1,tr[p*2].ma);
	tr[p*2+1].ma=max(tr[p].tag1,tr[p*2+1].ma);
	tr[p*2].tag1=max(tr[p].tag1,tr[p*2].tag1);
	tr[p*2+1].tag1=max(tr[p].tag1,tr[p*2+1].tag1);
	tr[p].tag1=0;
	
	tr[p*2].mi=min(tr[p].tag2,tr[p*2].mi);
	tr[p*2+1].mi=min(tr[p].tag2,tr[p*2+1].mi);
	tr[p*2].tag2=min(tr[p].tag2,tr[p*2].tag2);
	tr[p*2+1].tag2=min(tr[p].tag2,tr[p*2+1].tag2);
	tr[p].tag2=2100000000;
}
inline void build(int p,int l,int r)
{
	tr[p].l=l;
	tr[p].r=r;
	if(l!=r)
	{
		int mid=(l+r)/2;
		build(p*2,l,mid);
		build(p*2+1,mid+1,r);
		up(p);
		tr[p].tag1=0;
		tr[p].tag2=2100000000;
	}
	else
	{
		tr[p].ma=0;
		tr[p].mi=2100000000;
		tr[p].tag1=0;
		tr[p].tag2=2100000000;
	}
}
inline void change1(int p,int l,int r,int x)
{
	if(l<=tr[p].l&&tr[p].r<=r)
	{
		tr[p].ma=max(tr[p].ma,x);
		tr[p].tag1=max(tr[p].tag1,x);
	}
	else
	{
		push(p);
		int mid=(tr[p].l+tr[p].r)/2;
		if(l<=mid)
			change1(p*2,l,r,x);
		if(r>mid)
			change1(p*2+1,l,r,x);
		up(p);
	}
}
inline void change2(int p,int l,int r,int x)
{
	if(l<=tr[p].l&&tr[p].r<=r)
	{
		tr[p].mi=min(tr[p].mi,x);
		tr[p].tag2=min(tr[p].tag2,x);
	}
	else
	{
		push(p);
		int mid=(tr[p].l+tr[p].r)/2;
		if(l<=mid)
			change2(p*2,l,r,x);
		if(r>mid)
			change2(p*2+1,l,r,x);
		up(p);
	}
}
inline int ask1(int p,int l,int r)
{
	if(l<=tr[p].l&&tr[p].r<=r)
		return tr[p].ma;
	else
	{
		push(p);
		int mid=(tr[p].l+tr[p].r)/2;
		int ans=0;
		if(l<=mid)
			ans=max(ans,ask1(p*2,l,r));
		if(r>mid)
			ans=max(ans,ask1(p*2+1,l,r));
		up(p);
		return ans;
	}
}
inline int ask2(int p,int l,int r)
{
	if(l<=tr[p].l&&tr[p].r<=r)
		return tr[p].mi;
	else
	{
		push(p);
		int mid=(tr[p].l+tr[p].r)/2;
		int ans=2100000000;
		if(l<=mid)
			ans=min(ans,ask2(p*2,l,r));
		if(r>mid)
			ans=min(ans,ask2(p*2+1,l,r));
		up(p);
		return ans;
	}
}
int a[200001];
struct ques
{
	int l,r;
	int x,s,p;
}b[200001],c[200001];
inline bool cmp1(ques x,ques y)
{
	return x.l<y.l;
}
inline bool cmp2(ques x,ques y)
{
	return x.r<y.r;
}
int main()
{
	int n,m;
	while(scanf("%d%d",&n,&m)!=EOF)
	{
		int i,j;
		for(i=1;i<=n-1;i++)
			scanf("%d",&a[i]);
		build(1,1,n-1);
		int s,t;
		for(j=1;j<=m;j++)
		{
			scanf("%d%d",&s,&t);
			if(s>(t-1))
			{
				int tt=s;
				s=t;
				t=tt;
			}
			change1(1,s,t-1,j);
			change2(1,s,t-1,j);
		}
		for(i=1;i<=n-1;i++)
		{
			b[i].l=ask2(1,i,i);
			b[i].r=ask1(1,i,i);
			b[i].p=i;
			c[i].l=b[i].l;
			c[i].r=b[i].r;
			c[i].p=i;
		}
		sort(b+1,b+n,cmp1);
		sort(c+1,c+n,cmp2);
		int j1=1,j2=1;
		int ans=0;
		for(i=1;i<=m;i++)
		{
			while(j1<=n-1&&b[j1].l<=i)
			{
				if(b[j1].l<=b[j1].r)
					ans+=a[b[j1].p];
				j1++;
			}
			while(j2<=n-1&&c[j2].r<i)
			{
				if(c[j2].l<=c[j2].r)
					ans-=a[c[j2].p];
				j2++;
			}
			printf("%d\n",ans);
		}
	}
	return 0;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值