题意
给一个长度为(n)的数组(a)。(m)次询问,每次询问([S_i,E_i])中的子串和不超过(U_i)的最大值是多少。
思路
显然,可以发现是一个三位偏序题。询问(max{sum[l,r] | [-l,r,sum[l,r]]le[-S_i,E_i,U_i]})。
然后就有多种方法,可以分块+树状数组((O(sqrt{n}*logn*m+logn*n^2+(n^2+m)log(n^2+m))),询问+插入+排序),也可以用二维树状数组((O((n^2+m)log^2n+(n^2+m)log(n^2+m)))),也可以cdq分治((O((n^2+m)*log(n^2+m)*logn+(n^2+m)log(n^2+m))))+卡常。。
代码
cdq分治
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const int maxn = 2e3 + 5;
const int maxm = 2e5 + 5;
const ll inf = 1e18;
int a[maxn];
ll sum[maxn];
int s[maxm], e[maxm];
ll u[maxm];
struct IO{
#define MAXSIZE (1 << 20)
#define isdigit(x) (x >= '0' && x <= '9')
char buf[MAXSIZE], *p1, *p2;
IO() : p1(buf), p2(buf) {}
inline char gc(){
if (p1 == p2)
p2 = (p1 = buf) + fread(buf, 1, MAXSIZE, stdin);
return p1 == p2 ? ' ' : *p1++;
}
inline bool blank(char ch){
return ch == ' ' || ch == '
' || ch == '
' || ch == ' ';
}
template <class T>
inline void read(T &x){
bool sign = 0;
x = 0;
char ch = gc();
for (; !isdigit(ch); ch = gc())
if (ch == '-')
sign = 1;
for (; isdigit(ch); ch = gc())
x = x * 10 + (ch - '0');
if (sign)
x = -x;
}
} io;
struct Q{
int l, r;
ll val;
int id;
} q[maxm + maxn * maxn], tmp[maxm + maxn * maxn];
int qcnt;
ll ans[maxm];
void cmax(ll &x, ll y){
if (y > x)
x = y;
}
struct Bit{
ll data[maxn];
Bit(){
fill(data, data + maxn, -inf);
}
void insert(int pos, ll val){
for (; pos < maxn; pos += (pos & -pos))
cmax(data[pos], val);
}
void clear(int pos){
for (; pos < maxn; pos += (pos & -pos))
data[pos] = -inf;
}
ll max(int pos){
ll ans = -inf;
for (; pos > 0; pos -= (pos & -pos))
cmax(ans, data[pos]);
return ans;
}
} bit;
void cdq(int l, int r)
{
if (l == r)
return;
int mid = (l + r) / 2;
cdq(l, mid);
cdq(mid + 1, r);
int id = l;
vector<int> cl;
for (int i = l, j = mid + 1; i <= mid || j <= r;)
{
if (j > r || i <= mid && q[i].l <= q[j].l)
{
tmp[id++] = q[i];
if (q[i].id == 0)
{
cl.push_back(q[i].r);
bit.insert(q[i].r, q[i].val);
}
i++;
}
else
{
tmp[id++] = q[j];
if (q[j].id)
cmax(ans[q[j].id], bit.max(q[j].r));
j++;
}
}
for (int i = l; i <= r; i++)
q[i] = tmp[i];
for (int r : cl)
bit.clear(r);
}
int main()
{
int n, m;
io.read(n);
io.read(m);
for (int i = 1; i <= n; i++)
{
io.read(a[i]);
sum[i] = sum[i - 1] + a[i];
}
for (int i = 1; i <= m; i++)
{
io.read(s[i]);
io.read(e[i]);
io.read(u[i]);
q[++qcnt] = {-s[i], e[i], u[i], i};
ans[i] = -inf;
}
for (int i = 1; i <= n; i++)
for (int j = i; j <= n; j++)
q[++qcnt] = {-i, j, sum[j] - sum[i - 1], 0};
sort(q + 1, q + qcnt + 1, [](Q x, Q y) {
if (x.val != y.val)
return x.val < y.val;
else if (x.l != y.l)
return x.l < y.l;
else if (x.r != y.r)
return x.r < y.r;
else
return x.id < y.id;
});
cdq(1, qcnt);
for (int i = 1; i <= m; i++)
{
if (ans[i] == -inf)
printf("NONE
");
else
printf("%lld
", ans[i]);
}
return 0;
}