[Ynoi2009] rprmq1 题解
考虑猫树,对第一维离线分治,类似树套树写法即可,原因是我们在一旦找到了一个点,可以从这个点往后扫描线,跑历史最大值,这个东西不容易撤销处理,所以要分治找到合适的点。
#include <bits/stdc++.h>
#define int long long
#define lid (id<<1)
#define rid (id<<1|1)
using namespace std;
const int maxn=5e4+10;
int n,m,Q,tot,ans[maxn*10],x,y,xx,yy,z,op;
struct edge{
int x;
int l;
int r;
int val;
};
struct node{
int l;
int r;
int val;
};
struct edges{
int x;
int l;
int r;
int op;
};
struct nodes{
int mx;
int tag;
int lazy;
int his_mx;
int lazy_mx;
}tree[maxn<<3];
vector<node>han[maxn<<2];
vector<edge>ll[maxn<<2],rr[maxn<<2];
vector<edges>ql[maxn<<2],qr[maxn<<2];
void push_tag(int id,long long q,long long w){
tree[id].his_mx=max(tree[id].his_mx,tree[id].mx+w);
tree[id].lazy_mx=max(tree[id].lazy_mx,tree[id].lazy+w);
tree[id].lazy+=q;
tree[id].mx+=q;
return;
}
inline void clears(int id){
if(tree[id].lazy||tree[id].lazy_mx){
push_tag(lid,tree[id].lazy,tree[id].lazy_mx);
push_tag(rid,tree[id].lazy,tree[id].lazy_mx);
tree[id].lazy=0;
tree[id].lazy_mx=0;
}
tree[id].his_mx=tree[id].mx;
tree[id].lazy=0;
tree[id].tag=1;
return;
}
inline void push_down(int id){
if(tree[id].tag){
clears(lid);
clears(rid);
tree[id].tag=0;
}
if(tree[id].lazy_mx||tree[id].lazy){
push_tag(lid,tree[id].lazy,tree[id].lazy_mx);
push_tag(rid,tree[id].lazy,tree[id].lazy_mx);
tree[id].lazy=0;
tree[id].lazy_mx=0;
}
return;
}
inline void push_up(int id){
tree[id].mx=max(tree[lid].mx,tree[rid].mx);
tree[id].his_mx=max(tree[lid].his_mx,tree[rid].his_mx);
return;
}
inline void add(int id,int l,int r,int q,int w,int qw){
// if(id==1){
// cout<<q<<' '<<w<<' '<<qw<<'\n';
// }
if(q<=l&&r<=w){
tree[id].lazy+=qw;
tree[id].mx+=qw;
tree[id].lazy_mx=max(tree[id].lazy_mx,tree[id].lazy);
tree[id].his_mx=max(tree[id].his_mx,tree[id].mx);
return;
}
int mid=(l+r)/2;
push_down(id);
if(q<=mid){
add(lid,l,mid,q,w,qw);
}
if(w>mid){
add(rid,mid+1,r,q,w,qw);
}
push_up(id);
return;
}
inline int query(int id,int l,int r,int q,int w){
if(q<=l&&r<=w){
return tree[id].his_mx;
}
int mid=(l+r)/2;
push_down(id);
if(w<=mid){
return query(lid,l,mid,q,w);
}
else if(q>mid){
return query(rid,mid+1,r,q,w);
}
else{
return max(query(lid,l,mid,q,w),query(rid,mid+1,r,q,w));
}
}
int cmp1(edge q,edge w){
if(q.x==w.x){
return q.val<w.val;
}
return q.x>w.x;
}
int cmp2(edges q,edges w){
return q.x>w.x;
}
int cmp3(edge q,edge w){
if(q.x==w.x){
return q.val<w.val;
}
return q.x<w.x;
}
int cmp4(edges q,edges w){
return q.x<w.x;
}
inline void adds(int id,int l,int r,int q,int w){
if(q<=l&&r<=w){
han[id].push_back((node){y,yy,z});
return;
}
int mid=(l+r)/2;
if(q<=mid){
ll[id].push_back((edge){min(w,mid),y,yy,z});
ll[id].push_back((edge){q-1,y,yy,-z});
}
if(w>mid){
rr[id].push_back((edge){max(q,mid),y,yy,z});
rr[id].push_back((edge){w+1,y,yy,-z});
}
if(q<=mid){
adds(lid,l,mid,q,w);
}
if(w>mid){
adds(rid,mid+1,r,q,w);
}
return;
}
inline void ad(int id,int l,int r,int q,int w){
int mid=(l+r)/2;
if(q<=mid&&w>=mid){
ql[id].push_back((edges){q,y,yy,op});
qr[id].push_back((edges){w,y,yy,op});
return;
}
if(q<=mid){
ad(lid,l,mid,q,w);
}
if(w>mid){
ad(rid,mid+1,r,q,w);
}
return;
}
inline void init(int id,int l,int r){
for(int i=0;i<han[id].size();i++){
add(1,1,n,han[id][i].l,han[id][i].r,han[id][i].val);
}
int tp1,tp2,mid=(l+r)/2;
if(ql[id].size()){
sort(ll[id].begin(),ll[id].end(),cmp1);
sort(ql[id].begin(),ql[id].end(),cmp2);
tp1=-1,tp2=-1;
clears(1);
for(int i=mid;i>=l;i--){
while(tp1+1<ll[id].size()&&ll[id][tp1+1].x==i){
tp1++;
add(1,1,n,ll[id][tp1].l,ll[id][tp1].r,ll[id][tp1].val);
}
while(tp2+1<ql[id].size()&&ql[id][tp2+1].x==i){
tp2++;
ans[ql[id][tp2].op]=max(ans[ql[id][tp2].op],query(1,1,n,ql[id][tp2].l,ql[id][tp2].r));
}
}
while(tp1+1<ll[id].size()){
tp1++;
add(1,1,n,ll[id][tp1].l,ll[id][tp1].r,ll[id][tp1].val);
}
}
if(qr[id].size()){
sort(rr[id].begin(),rr[id].end(),cmp3);
sort(qr[id].begin(),qr[id].end(),cmp4);
tp1=-1,tp2=-1;
clears(1);
for(int i=mid;i<=r;i++){
while(tp1+1<rr[id].size()&&rr[id][tp1+1].x==i){
tp1++;
add(1,1,n,rr[id][tp1].l,rr[id][tp1].r,rr[id][tp1].val);
}
while(tp2+1<qr[id].size()&&qr[id][tp2+1].x==i){
tp2++;
ans[qr[id][tp2].op]=max(ans[qr[id][tp2].op],query(1,1,n,qr[id][tp2].l,qr[id][tp2].r));
}
}
while(tp1+1<rr[id].size()){
tp1++;
add(1,1,n,rr[id][tp1].l,rr[id][tp1].r,rr[id][tp1].val);
}
}
if(l==r){
for(int i=0;i<han[id].size();i++){
add(1,1,n,han[id][i].l,han[id][i].r,-han[id][i].val);
}
return;
}
init(lid,l,mid);
init(rid,mid+1,r);
for(int i=0;i<han[id].size();i++){
add(1,1,n,han[id][i].l,han[id][i].r,-han[id][i].val);
}
return;
}
signed main(){
ios::sync_with_stdio(0);
cin.tie(0),cout.tie(0);
cin>>n>>m>>Q;
for(int i=1;i<=m;i++){
cin>>x>>y>>xx>>yy>>z;
adds(1,1,n,x,xx);
}
for(int i=1;i<=Q;i++){
tot++;
op=i;
cin>>x>>y>>xx>>yy;
ad(1,1,n,x,xx);
}
init(1,1,n);
for(int i=1;i<=Q;i++){
cout<<ans[i]<<'\n';
}
return 0;
}
浙公网安备 33010602011771号