【五一省选集训day4】Mansion
【五一省选集训day4】Mansion
注意,本题要求输出最大值,不要把最大值看成编号……srds 好像只有我看错了。
这个东西一看就很能用莫队做。
用莫队按 \(l\) 分块,再按 \(r\) 排序。维护一棵线段树,每次移动对线段树进行单点修改和区间求 \(\max\),一共 \(n\sqrt{n}\) 次移动,总时间复杂度是 \(O(n\sqrt{n}\log n)\) 的。可以获得 \(80pts\)。
感觉根号是不好消的,但是这个 \(\log\) 就看起来很能优化。
因为是求 \(\max\) 我们考虑回滚莫队来避免减法。回滚莫队也是 \(O(n\sqrt{n})\) 的。注意到我们每次移动都要修改,修改 \(O(n\sqrt{n})\) 次,而查询最大值只有 \(O(n)\) 次。这个 \(\sqrt{n}\) 的差距让我们想到用分块来代替线段树做。线段树两种操作都是 \(\log\) 的,但分块是修改 \(O(1)\),查询 \(O(\sqrt{n})\) 的!改成分块,总时间复杂度 \(O\sqrt{n}\)。
注意回滚莫队第一块除以 \(T\) 是 \(0\),而为空的 \(que_0\) 除以 \(T\) 也是 \(0\),记得初始化 \(\frac{que_0}{T}=-1\),否则 \(0\) 会成为第一块开头,而不是 \(1\)。害我调了一下午
code
#include<bits/stdc++.h>
//#define LOCAL
#define int ll
#define sf scanf
#define pf printf
#define rep(x,y,z) for(int x=y;x<=z;x++)
#define per(x,y,z) for(int x=y;x>=z;x--)
#define isdigit(x) ((x>='0')&&(x<='9'))
#define ls u<<1
#define rs u<<1|1
using namespace std;
typedef long long ll;
const int N=150500,T=395;
template <typename T>
inline void read(T &x){
x=0;
char ch=getchar();
for(;!isdigit(ch);ch=getchar());
for(;isdigit(ch);ch=getchar()) x=(x<<3)+(x<<1)+ch-'0';
}
template <typename T>
inline void write(T x){
static int st[20];
int cnt=0;
do{
st[cnt++]=x%10;
x/=10;
}while(x);
while(cnt) putchar(st[--cnt]+'0');
}
template <typename T>
inline void write (T x,char ch){
write(x);
putchar(ch);
}
int n,m,q,t;
struct node{
int a,b;
}h[N];
struct que{
int t,id,l,r,vl,vr;
}qu[N];
int l,r,vl,vr;
bool cmp(que a,que b){
return a.t!=b.t?a.t<b.t:a.r<b.r;
}
ll s[N],mx[N/T+10],mxt[N/T+10];
ll anss[N];
void add(int k){
int a=h[k].a,b=h[k].b;
s[a]+=b;
int ta=a/T;
mx[ta]=max(mx[ta],s[a]);
}
void add2(int k){
int a=h[k].a,b=h[k].b;
s[a]+=b;
int ta=a/T;
mxt[ta]=max(mxt[ta],s[a]);
}
void del2(int k){
int a=h[k].a,b=h[k].b;
s[a]-=b;
}
ll s2[N];
int L,R;
ll solve(ll l,ll r){
ll ans=0;
if(l/T==r/T){
rep(i,l,r) ans=max(ans,s[i]);
}else{
rep(i,l,l/T*T+T-1) ans=max(ans,s[i]);
rep(i,l/T+1,r/T-1) ans=max(ans,mxt[i]);
rep(i,r/T*T,r) ans=max(ans,s[i]);
}
return ans;
}
signed main(){
#ifdef LOCAL
freopen("in.txt","r",stdin);
freopen("my2.out","w",stdout);
#endif
read(n),read(m),read(q);
rep(i,1,n){
read(h[i].a);
}
rep(i,1,n) {
read(h[i].b);
}
rep(i,1,q){
read(l),read(r),read(vl),read(vr);
qu[i]={l/T,i,l,r,vl,vr};
}
sort(qu+1,qu+q+1,cmp);
qu[0].t=-1;
rep(i,1,q){
t=qu[i].t,l=qu[i].l,r=qu[i].r,vl=qu[i].vl,vr=qu[i].vr;
ll ans=0;
if(l/T==r/T){
qu[i].t=qu[i-1].t;
rep(j,l,r){
int a=h[j].a,b=h[j].b;
if(a<vl||a>vr) continue;
s2[a]+=b;
ans=max(ans,s2[a]);
}
rep(j,l,r){
int a=h[j].a;
s2[a]=0;
}
}else{
L=t*T+T;
if(t!=qu[i-1].t){
memset(s,0,sizeof(s));
memset(mx,0,sizeof(mx));
R=L-1;
}
while(R<r) {
R++;
add(R);
}
memcpy(mxt,mx,sizeof(mx));
while(L>l){
L--;
add2(L);
}
ans=solve(vl,vr);
L=t*T+T;
while(L>l){
L--;
del2(L);
}
}
anss[qu[i].id]=ans;
}
rep(i,1,q) write(anss[i],'\n');
}
本文来自博客园,作者:liyixin,转载请注明原文链接:https://www.cnblogs.com/liyixin0514/p/18406965