正常思路应该是移动l,r再算答案,我的做法是先移动值域再移动l,r。 TLE on #9 https://www.luogu.com.cn/record/112240091
#include <bits/stdc++.h>
using namespace std;
// #define int long long
#define rep(i, a, b) for (int i = a; i <= b; ++i)
#define drep(i, a, b) for (int i = a; i >= b; --i)
namespace FastIO
{
const int MAXSIZE = 1 << 20;
struct Reader
{
template <typename T>
Reader &operator>>(T &x)
{
char c = getchar();
T f = 1;
while (!isdigit(c))
c = getchar();
x = 0;
while (isdigit(c))
x = (x << 3) + (x << 1) + (c ^ 48), c = getchar();
x *= f;
return *this;
}
Reader &operator>>(char &c)
{
c = getchar();
while (c == ' ' || c == '\n')
c = getchar();
return *this;
}
Reader &operator>>(char *str)
{
int len = 0;
char c = getchar();
while (c == ' ' || c == '\n')
c = getchar();
while (c != ' ' && c != '\n' && c != '\r')
str[len++] = c, c = getchar();
str[len] = '\0';
return *this;
}
Reader() {}
} cin;
const char endl = '\n';
struct Writer
{
template <typename T>
Writer &operator<<(T x)
{
if (x == 0)
{
putchar('0');
return *this;
}
static int sta[111];
int top = 0;
while (x)
sta[++top] = x % 10, x /= 10;
while (top)
putchar(sta[top--] + '0');
return *this;
}
Writer &operator<<(char c)
{
putchar(c);
return *this;
}
Writer &operator<<(char *str)
{
int cur = 0;
while (str[cur])
putchar(str[cur++]);
return *this;
}
Writer &operator<<(const char *str)
{
int cur = 0;
while (str[cur])
putchar(str[cur++]);
return *this;
}
Writer() {}
} cout;
}
#define cin FastIO::cin
#define cout FastIO::cout
#define endl FastIO::endl
#define N 100000
#define S 320
int n, m, e[N + 5], p[N + 5], q[N + 5], bl[N + 5], cnt[N + 5];
int ans1, ans2;
struct ask
{
int a, b, l, r, id;
} Q[N + 5];
bool cmp(ask x, ask y)
{
if (bl[x.a] != bl[y.a])
return x.a < y.a;
if (bl[x.b] != bl[y.b])
return x.b < y.b;
if (bl[x.l] != bl[y.l])
return x.l < y.l;
return x.r < y.r;
}
signed main()
{
cin >> n >> m;
rep(i, 1, n) cin >> e[i];
rep(i, 1, N) bl[i] = (i - 1) / S + 1;
rep(i, 1, m) cin >> Q[i].l >> Q[i].r >> Q[i].a >> Q[i].b, Q[i].id = i;
sort(Q + 1, Q + m + 1, cmp);
int L = 1, R = 0, A = 1, B = 0;
rep(i, 1, m)
{
int l = Q[i].l, r = Q[i].r, a = Q[i].a, b = Q[i].b, id = Q[i].id;
while (a < A)
{
ans1 += cnt[--A];
ans2 += !!cnt[A];
}
while (a > A)
{
ans1 -= cnt[A];
ans2 -= !!cnt[A++];
}
while (b > B)
{
ans1 += cnt[++B];
ans2 += !!cnt[B];
}
while (b < B)
{
ans1 -= cnt[B];
ans2 -= !!cnt[B--];
}
while (l < L)
{
if (e[--L] >= a && e[L] <= b)
{
if (cnt[e[L]] == 0)
ans2++;
ans1++;
}
cnt[e[L]]++;
}
while (l > L)
{
if (e[L] >= a && e[L] <= b)
{
if (cnt[e[L]] == 1)
ans2--;
ans1--;
}
cnt[e[L++]]--;
}
while (r >= R)
{
if (e[++R] >= a && e[R] <= b)
{
if (cnt[e[R]] == 0)
ans2++;
ans1++;
}
cnt[e[R]]++;
}
while (r < R)
{
// R--;
if (e[R] >= a && e[R] <= b)
{
if (cnt[e[R]] == 1)
ans2--;
ans1--;
}
cnt[e[R--]]--;
}
p[id] = ans1, q[id] = ans2;
}
rep(i, 1, m) cout << p[i] << ' ' << q[i] << '\n';
return 0;
}