题目大意
给出 个任务,每项的重要值
工作 次,第 次从编号为 的项目里选择重要度最大的一项任务完成,所获得的进展量为 该任务的重要度。
求 次工作后的进展度
题目解析
明显的线段树,区间查找和修改
首先建一棵线段树,除了线段树必要的num,l,r之外,记录下来区间最大值w和当前区间最大值所在位置pos,询问时返回w和pos
并写一个更改函数对pos上的值进行更改并递归返回上层也进行更改。
代码
#include<bits/stdc++.h>
using namespace std;
int n,m,x,y,ans,w,pos;
struct A
{
int w,l,r,pos;
}a[1000005];
void fun(int k)
{
if(a[k*2].w>a[k*2+1].w)
a[k].w=a[k*2].w,a[k].pos=a[k*2].pos;
else
a[k].w=a[k*2+1].w,a[k].pos=a[k*2+1].pos;
}
void build(int l,int r,int num)
{
a[num].l=l;a[num].r=r;
if(l==r)
{
scanf("%d",&a[num].w);
a[num].pos=l;
return;
}
int mid=(l+r)>>1;
build(l,mid,num*2);
build(mid+1,r,num*2+1);
fun(num);
return;
}
void find(int num,int l,int r)
{
if(a[num].l==l&&a[num].r==r)
{
if(w<a[num].w)
{
w=a[num].w;
pos=a[num].pos;
}
return;
}
int mid=(a[num].l+a[num].r)/2;
if(y<=mid) find(num*2,l,r);
else if(x>mid) find(num*2+1,l,r);
else
find(num*2,l,mid),find(num*2+1,mid+1,r);
return;
}
void change(int num)
{
if(a[num].l==a[num].r)
{
a[num].w=0;
return;
}
int mid=(a[num].l+a[num].r)/2;
if(pos<=mid) change(num*2);
else change(num*2+1);
fun(num);
return;
}
int main()
{
scanf("%d%d",&n,&m);
build(1,n,1);
for(int i=1;i<=m;i++)
{
w=0;
scanf("%d%d",&x,&y);
find(1,x,y);
(ans+=w*((x+y)%2011)%2011)%=2011;
change(1);
}
cout<<ans;
}