P7706 文文的攝影佈置 題解
原題
讀完題,發現是線段樹。單點修改+區間查詢。
不過查詢的值有些奇怪,就是了,我們考慮用線段樹維護這個 ψ 值(下稱待求值)。
對於一個區間的待求值,大概有四種情況:
如上圖四種情況分別為:
- 待求值最大值在左區間
- 待求值最大值在右區間
- \(a_i與b_j\) 在左區間
- \(b_j與a_k\) 在右區間
考慮合併的方式:
對於1,2,返回左右區間的較大的待求值。
對於3,4,維護左右區間的 \(lt\) 與 \(rt\) ,分別代表,較大的 \(a_i-b_j\) 及 較大的 \(a_k-_j\) ,更新時加上另一側較大值即可。
由此,得出線段樹結構體需要維護的值有:\(maxx,minn,lt,rt,mx\) ,分別為最大的 \(a\) ,最小的 \(b\) ,較大的 \(a_i-b_j\) 及 較大的 \(a_k-_j\) ,和本區間的最大待求值。
於是可得程式碼:
#include <bits/stdc++.h>
#define seq(q, w, e) for (int q = w; q <= e; q++)
#define ll long long
using namespace std;
const int maxn = 5e5+10;
const ll inf=-1e8-10;
struct pect{
ll s,b; //存圖片
}a[maxn];
struct node{
ll maxx,minn; //maxx為區間a最大,minn為區間b最小
ll lt,rt,mx; //lt為區間 min(bj)-ai,rt為區間 ak-min(bj)
}tree[maxn<<2];
ll ls(ll p){return p<<1;}
ll rs(ll p){return p<<1|1;}
node up_date(node a,node b){
node p;
p.maxx=max(a.maxx,b.maxx);
p.minn=min(a.minn,b.minn);
p.lt=a.maxx-b.minn;
p.rt=b.maxx-a.minn;
p.lt=max(p.lt,max(a.lt,b.lt)); //三種情況取最大
p.rt=max(p.rt,max(a.rt,b.rt));
p.mx=max(a.lt+b.maxx,b.rt+a.maxx); //情況取最大
p.mx=max(p.mx,max(a.mx,b.mx));
return p;
}
void push_up(ll p){
tree[p]=up_date(tree[ls(p)],tree[rs(p)]);
}
void build(ll p,ll pl,ll pr){
if(pl==pr){
tree[p].maxx=a[pl].s;
tree[p].minn=a[pl].b;
tree[p].lt=tree[p].rt=tree[p].mx=inf;
return;
}
ll mid=(pl+pr)>>1;
build(ls(p),pl,mid);
build(rs(p),mid+1,pr);
push_up(p);
}
void change(ll x,ll d,ll p,ll pl,ll pr,ll op){
if(pl==pr){
if(op==1) tree[p].maxx=d;
if(op==2) tree[p].minn=d;
return;
}
ll mid=(pl+pr)>>1;
if(x<=mid) change(x,d,ls(p),pl,mid,op);
else change(x,d,rs(p),mid+1,pr,op);
push_up(p);
}
node query(ll l,ll r, ll p,ll pl,ll pr){
if(l<=pl&&r>=pr)
return tree[p];
ll mid=(pl+pr)>>1;
if(l>mid) return query(l,r,rs(p),mid+1,pr);
if(r<=mid) return query(l,r,ls(p),pl,mid);
return up_date(query(l,r,ls(p),pl,mid),query(l,r,rs(p),mid+1,pr));
}
ll n,m,op;
signed main()
{
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
cin>>n>>m;
seq(i,1,n){
cin>>a[i].s;
}
seq(i,1,n){
cin>>a[i].b;
}
build(1,1,n);
while(m--){
int x,y;
cin>>op>>x>>y;
if(op==1){
change(x,y,1,1,n,1);
}
if(op==2){
change(x,y,1,1,n,2);
}
if(op==3){
cout<<query(x,y,1,1,n).mx<<endl;
}
}
return 0;
}