day2018.8.18模拟赛总结(待补)

T1:

题目大意:给定一列n座城市,第i个城市买入宝石和卖出宝石的价格均为ai.

现在给出m个操作,分为两类:

1.格式1 l r,表示查询从l走到r的路程中最多能赚到多少钱,假设初始有无限多的钱且最初没有宝石,但是路程中你最多只能带一颗宝石.

2.格式1 l r x y,表示修改[l,r]内的城市l的宝石价格为x,然后是修改成公差为y的等差数列.

首先很明显这是一道数据结构题,但是不论是分块还是线段树都不好维护,又由于要修改成等差数列,所以我们可以很容易的想到先进行差分.

差分完了之后,我们可以很容易的看出查询[l,r]其实等价于查询[l+1,r]的差分数组中的正数和.

那么这道题就好做了.

代码如下:

#include<bits/stdc++.h>
  using namespace std;
#define Abigail inline void
typedef long long LL;
const int N=200000;
struct tree{
  bool flag;
  int l,r;
  LL sum,ans,tag;
}tr[N*5];
int n,m;
LL a[N+9];
void pushup(int k){
  int ls=k<<1,rs=ls|1;
  tr[k].sum=tr[ls].sum+tr[rs].sum;
  tr[k].ans=tr[ls].ans+tr[rs].ans;
}
void update(int k,LL num){
  tr[k].flag=1;
  tr[k].tag=num;
  tr[k].sum=num*(tr[k].r-tr[k].l+1);
  tr[k].ans=max(0LL,tr[k].sum);
}
void pushdown(int k){
  if (!tr[k].flag) return; 
  update(k<<1,tr[k].tag);update(k<<1|1,tr[k].tag);
  tr[k].flag=0;
}
void build(int L,int R,int k=1){
  tr[k].l=L;tr[k].r=R;
  if (L==R){
    tr[k].sum=a[L];
    tr[k].ans=max(a[L],0LL);
    return;
  }
  int mid=L+R>>1;
  build(L,mid,k<<1);build(mid+1,R,k<<1|1);
  pushup(k);
}
void change(int L,int R,LL num,int k=1){
  if (L==tr[k].l&&R==tr[k].r){
    update(k,num);
    return;
  }
  pushdown(k);
  int mid=tr[k].l+tr[k].r>>1;
  if (R<=mid) change(L,R,num,k<<1);
  else if (L>mid) change(L,R,num,k<<1|1);
    else change(L,mid,num,k<<1),change(mid+1,R,num,k<<1|1);
  pushup(k);
}
struct tree1{
  LL ans,sum;
};
tree1 query(int L,int R,int k=1){
  if (L==tr[k].l&&R==tr[k].r) return (tree1){tr[k].ans,tr[k].sum};
  pushdown(k);
  int mid=tr[k].l+tr[k].r>>1;
  if (R<=mid) return query(L,R,k<<1);
  else if (L>mid) return query(L,R,k<<1|1);
    else {
      tree1 u=query(L,mid,k<<1),v=query(mid+1,R,k<<1|1),o;
      o.sum=u.sum+v.sum;
      o.ans=u.ans+v.ans;
      return o;
    }
}
Abigail into(){
  scanf("%d%d",&n,&m);
  for (int i=1;i<=n;i++)
    scanf("%lld",&a[i]);
}
Abigail work(){
  for (int i=n;i>=1;i--)
    a[i]-=a[i-1];
  build(1,n);
  int l,r,opt;
  LL x,y,gl,gr;
  for (int i=1;i<=m;i++){
    scanf("%d%d%d",&opt,&l,&r);
    if (opt==1){
      if (l==r) printf("%lld\n",0LL);
      else printf("%lld\n",query(l+1,r).ans);
    }else{
      scanf("%lld%lld",&x,&y);
      if (r<n) gr=query(1,r+1).sum;
      if (l>1) gl=query(1,l-1).sum;
      else gl=0;
      change(l,l,x-gl);
      if (l<r) change(l+1,r,y);
      if (r<n) change(r+1,r+1,gr-query(1,r).sum);
    }
  }
}
Abigail outo(){
}
int main(){
  freopen("gem.in","r",stdin);
  freopen("gem.out","w",stdout);
  into();
  work();
  outo();
  return 0;
}

这题就这样考场AC了,我在考场的时候竟然下意识的写了一份维护最大子段和的代码...

T2T3算法完全不会啊...

猜你喜欢

转载自blog.csdn.net/hzk_cpp/article/details/81808542