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算法完全不会啊...