[3.2] 网站计划

题目大意

给出 n n 个任务,每项的重要值 v [ i ] v[i]

工作 m m 次,第 j j 次从编号为 l [ j ]   r [ j ] l[j]~r[j] 的项目里选择重要度最大的一项任务完成,所获得的进展量为 ( l [ j ] + r [ j ] ) (l[j]+r[j])* 该任务的重要度。

m m 次工作后的进展度

题目解析

明显的线段树,区间查找和修改

首先建一棵线段树,除了线段树必要的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;
}

猜你喜欢

转载自blog.csdn.net/weixin_43909855/article/details/88076712
3.2
今日推荐