您的位置:首页 > 其它

2016多校训练Contest10: 1005 Road hdu5861

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