Nguồn đề bài: http://vn.spoj.com/problems/QMAX/
1. Đề bài QMAX spoj
Cho một dãy gồm n phần tử có giá trị ban đầu bằng 0.
Cho m phép biến đổi, mỗi phép có dạng (u, v, k): tăng mỗi phần tử từ vị trí u đến vị trí v lên k đơn vị.
Cho q câu hỏi, mỗi câu có dạng (u, v): cho biết phần tử có giá trị lớn nhất thuộc đoạn [u, v]
Giới hạn
- n, m, q <= 50000
- k > 0
- Giá trị của một phần tử luôn không vượt quá 231-1
Input
- Dòng 1: n, m
- m dòng tiếp theo, mỗi dòng chứa u, v, k cho biết một phép biến đổi
- Dòng thứ m+2: p
- p dòng tiếp theo, mỗi dòng chứa u, v cho biết một phép biến đổi
Output
- Gồm p dòng chứa kết quả tương ứng cho từng câu hỏi.
Example
Input: 6 2 1 3 2 4 6 3 1 3 4 Output: 3
2. Hướng dẫn QMAX spoj
– xử lí phần truy vấn giống như bài MTHCN bạn có thể tham khảo tại đây: https://kienthuc24h.com/2015/01/11/mthcn-spoj-hinh-chu-nhat-ki-la/
– sau đó dùng cây Interval Tree để giải quyết 😀
3. code tham khảo QMAX spoj (pascal, C++)
Pascal
uses math;
const fi='';
nmax=50000;
type data=longint;
var
f:text;
T,A:array[0..nmax*4] of data;
m,n,q:data;
procedure napdulieu(i,l,r:data);
var mid:data;
begin
if l=r then
begin
T[i]:=a[L];
exit;
end;
mid:=(l+r) div 2;
napdulieu(i*2,l,mid);
napdulieu(i*2+1,mid+1,r);
T[I]:=max(T[i*2],T[i*2+1]);
end;
function timmax(i,l,r,u,v:data):data;
var mid,maxtrai,maxphai:data;
begin
if (v<l) or (r<u) then
exit(0)
else
if (u<=l) and (r<=v) then
exit(T[i])
else
begin
mid:=(l+r) div 2;
maxtrai:=timmax(i*2,l,mid,u,v);
maxphai:=timmax(i*2+1,mid+1,r,u,v);
exit(max(maxtrai,maxphai));
end;
end;
procedure xuli;
var i,j,u,v,k:data;
begin
assign(f,fi); reset(f);
readln(f,n,m);
for i:=0 to n do
a[i]:=0;
for i:=1 to m do
begin
readln(f,u,v,k);
a[u]:=a[u]+k;
a[v+1]:=a[v+1]-k;
end;
for i:=1 to n do
a[i]:=a[i]+a[i-1];
napdulieu(1,1,n);
readln(f,q);
for i:=1 to q do
begin
readln(f,u,v);
writeln(timmax(1,1,n,u,v));
end;
close(f);
end;
begin
xuli;
end.c++
#include <bits/stdc++.h>
using namespace std;
int n,m,q;
vector<int> a;
vector<int> T;
int res;
void Update(int k, int l, int r, int i)
{
if(l>i || r<i) return;
if(l==r)
{
T[k]=a[i];
return;
}
int m=(l+r)/2;
Update(2*k,l,m,i);
Update(2*k+1,m+1,r,i);
T[k]=max(T[2*k],T[2*k+1]);
}
void Query(int k, int l, int r, int dau, int cuoi)
{
if(l>cuoi || r<dau) return;
if(dau<=l && cuoi>=r)
{
res=max(res,T[k]);
return;
}
int m=(l+r)/2;
Query(2*k,l,m,dau,cuoi);
Query(2*k+1,m+1,r,dau,cuoi);
}
void Init()
{
cin>>n>>m;
a.resize(n+2);
T.resize(4*n);
for (int i=0;i<m;i++)
{
int u,v,k;
cin>>u>>v>>k;
a[u]+=k;
a[v+1]-=k;
}
for (int i=1;i<=n;i++)
{
a[i]+=a[i-1];
Update(1,1,n,i);
}
}
void Solve()
{
cin>>q;
for (int i=0;i<q;i++)
{
int u,v;
cin>>u>>v;
res=0;
Query(1,1,n,u,v);
cout<<res<<endl;
}
}
int main()
{
Init();
Solve();
}