laekov

BZOJ3236 作业

好厉害的数据结构题,时限太吓人了。


最初想写莫队的,但是在数据范围下屈服了。


用可持久化线段树套可持久化线段树来维护可过。虽然跑了97s。本机跑得快得多,虽然有两个点被卡到了18s。


#include <cstdio>

#include <cctype>

#include <cstring>

#include <algorithm>


using namespace std;


struct seg {

int v, ls, rs;

};


#define readInt(_s_) {\

_s_ = 0;\

int _d_ = 0;\

while (!isdigit(_d_ = getchar()));\

while ((_s_ = _s_ * 10 + _d_ - 48), isdigit(_d_ = getchar()));\

}


const int maxn = 100009;

const int maxl = 20;

const int maxnd = maxn * maxl * maxl;


seg s[maxnd];

int n, m, t, a[maxn], d[maxn], c[maxn], *r[maxn], sp, rt[maxn];


inline bool cmpP(int* a, int* b) {

return *a < *b;

}


#define vof(p) ((p)?(s[p].v):0)

#define lson(p) ((p)?(s[p].ls):0)

#define rson(p) ((p)?(s[p].rs):0)


int sgtIns(int q, int p0) {

int rt = ++ sp, p = rt;

int l = 0, r = n;

while (l < r) {

s[p]. v = vof(q) + 1;

int mid = (l + r) >> 1;

if (p0 <= mid) {

s[p]. rs = rson(q);

q = lson(q);

s[p]. ls = ++ sp;

p = s[p]. ls;

r = mid;

}

else {

s[p]. ls = lson(q);

q = rson(q);

s[p]. rs = ++ sp;

p = s[p]. rs;

l = mid + 1;

}

}

s[p]. v = vof(q) + 1;

return rt;

}


int psgtIns(int q, int p0, int v0) {

int rt = ++ sp, p = rt;

int l = 1, r = t;

while (l < r) {

s[p]. v = sgtIns(vof(q), v0);

int mid = (l + r) >> 1;

if (p0 <= mid) {

s[p]. rs = rson(q);

q = lson(q);

s[p]. ls = ++ sp; 

p = s[p]. ls;

r = mid;

}

else {

s[p]. ls = lson(q);

q = rson(q);

s[p]. rs = ++ sp;

p = s[p]. rs;

l = mid + 1;

}

}

s[p]. v = sgtIns(vof(q), v0);

return rt;

}


void dispNums() {

for (int i = 1; i <= n; ++ i)

r[i - 1] = a + i;

sort(r, r + n, cmpP);

t = 0;

for (int i = 0, l = *r[0] - 1; i < n; ++ i)

if (*r[i] == l)

*r[i] = t;

else {

d[++ t] = *r[i];

   l = *r[i];

*r[i] = t;

}

d[++ t] = *r[n - 1] + 1;

memset(c, 0, sizeof(c));

rt[0] = 0;

sp = 0;

for (int i = 1; i <= n; ++ i) {

rt[i] = psgtIns(rt[i - 1], a[i], c[a[i]]);

c[a[i]] = i;

}

}


int sgtQry(int p, int p0) {

int ans = 0;

int l = 0, r = n;

while (l < r && p) {

int mid = (l + r) >> 1;

if (p0 <= mid) {

r = mid;

p = lson(p);

}

else {

l = mid + 1;

ans += vof(lson(p));

p = rson(p);

}

}

if (p)

ans += vof(p);

return ans;

}


void psgtQry(int p, int p0, int v0, int& x, int& y) {

x = 0;

y = 0;

if (p0 == 0)

return;

int l = 1, r = t;

while (l < r && p) {

int mid = (l + r) >> 1;

if (p0 <= mid) {

r = mid;

p = lson(p);

}

else {

x += vof(vof(lson(p)));

y += sgtQry(vof(lson(p)), v0);

l = mid + 1;

p = rson(p);

}

}

if (p) {

x += vof(vof(p));

y += sgtQry(vof(p), v0);

}

}


void query(int l, int r, int a, int b) {

int tt = 0, ct = 0, x, y;

psgtQry(rt[r], b, l - 1, x, y);

tt += x;

ct += y;

psgtQry(rt[r], a - 1, l - 1, x, y);

tt -= x;

ct -= y;

psgtQry(rt[l - 1], b, l - 1, x, y);

tt -= x;

ct -= y;

psgtQry(rt[l - 1], a - 1, l - 1, x, y);

tt += x;

ct += y;

printf("%d %d\n", tt, ct);

}


int main() {

#ifndef ONLINE_JUDGE

freopen("in.txt", "r", stdin);

#endif


readInt(n);

readInt(m);

for (int i = 1; i <= n; ++ i)

readInt(a[i]);

dispNums();

while (m --) {

int l, r, a, b;

readInt(l);

readInt(r);

readInt(a);

readInt(b);

a = lower_bound(d, d + t, a) - d; 

b = upper_bound(d, d + t, b) - d - 1;

if (a > b)

puts("0 0");

else

query(l, r, a, b);

}

}


评论

© laekov | Powered by LOFTER