求助小清新分块题。。。。

P5065 [Ynoi2014] 不归之人与望眼欲穿的人们

_5011_ @ 2020-04-25 20:09:44

实在卡不动了。。。

TLE 95 分在线求卡。。。

#pragma GCC optimize("Ofast","-funroll-loops","-fdelete-null-pointer-checks")
#pragma GCC target("ssse3","sse3","sse2","sse","avx2","avx")
#include <iostream>
#include <cmath>
#include <cstring>
#include <cstdio>
using namespace std;

#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
char buf[1 << 21], *p1 = buf, *p2 = buf;

inline int qread() {
    register char c = getchar();
    register int x = 0, f = 1;
    while (c < '0' || c > '9') {
        if (c == '-') f = -1;
        c = getchar();
    }
    while (c >= '0' && c <= '9') {
        x = (x << 3) + (x << 1) + c - 48;
        c = getchar();
    }
    return x * f;
}

inline int Abs(const int& x) {return (x > 0 ? x : -x);}
inline int Max(const int& x, const int& y) {return (x > y ? x : y);}
inline int Min(const int& x, const int& y) {return (x < y ? x : y);}

const int S = 250;
struct Block {
    pair <int, int> pre[35], suf[35], ans[35];
    int pretop, suftop, anstop, mx[S + 5], val[S + 5], n, bl, br;
    Block() {
        pretop = suftop = n = bl = br = 0;
        memset(mx, 0, sizeof(mx));
        memset(val, 0, sizeof(val));
    }
    //O(sqrtnloga)
    inline void Rebuild() {
        pretop = 0;
        memset(mx, 0xcf, sizeof(mx));
        for (register int i = 1;i <= n;i++) {
            pair <int, int> cur[35];
            int curtop = 0;
            for (register int j = 1;j <= pretop;j++) {
                if (!(val[i] & (1 << pre[j].second))) cur[++curtop] = pre[j];
            }
            pretop = curtop;
            for (register int j = 1;j <= pretop;j++) pre[j] = cur[j];
            for (register int j = 0;j < 31;j++) {
                if (val[i] & (1 << j)) pre[++pretop] = make_pair(i + bl - 1, j);
            }
            register int curval = 0;
            for (register int j = pretop;j >= 1;j--) {
                curval |= (1 << pre[j].second);
                mx[i - pre[j].first + bl] = Max(mx[i - pre[j].first + bl], curval);
            }
        }
        suftop = 0;
        for (register int i = n;i >= 1;i--) {
            pair <int, int> cur[35];
            int curtop = 0;
            for (register int j = 0;j < 31;j++) {
                if (val[i] & (1 << j)) cur[++curtop] = make_pair(i + bl - 1, j);
            }
            for (register int j = 1;j <= suftop;j++) {
                if (!(val[i] & (1 << suf[j].second))) cur[++curtop] = suf[j];
            }
            suftop = curtop;
            for (register int j = 1;j <= suftop;j++) suf[j] = cur[j];
        }
        for (register int i = 1;i <= n;i++) mx[i] = Max(mx[i - 1], mx[i]);
    }
};
Block blk[int(50000 / S) + 20];
int n, m, a[50005], pos[50005];

//O(loga)
inline void CalcAns(int i) {
    blk[i].anstop = 0;
    register int lst[35] = {0};
    for (register int j = 1;j <= blk[i].pretop;j++) lst[blk[i].pre[j].second] = blk[i].pre[j].first;
    for (register int j = 1;j <= blk[i - 1].anstop;j++) {
        if (!lst[blk[i - 1].ans[j].second]) blk[i].ans[++blk[i].anstop] = blk[i - 1].ans[j];
    }
    for (register int j = 1;j <= blk[i].pretop;j++) blk[i].ans[++blk[i].anstop] = blk[i].pre[j];
}

//O(n)
inline void Read() {
    n = qread(); m = qread();
    for (register int i = 1;i <= n;i++) a[i] = qread(), pos[i] = (i - 1) / S + 1;
}

//O(n)
inline void Prefix() {
    for (register int i = 1;i <= pos[n];i++) {
        blk[i].bl = (i - 1) * S + 1;
        blk[i].br = Min(i * S, n);
        for (register int j = blk[i].bl;j <= blk[i].br;j++) blk[i].val[j - blk[i].bl + 1] = a[j];
        blk[i].n = blk[i].br - blk[i].bl + 1;
        blk[i].Rebuild();
    }
    for (register int i = 1;i <= pos[n];i++) CalcAns(i);
}

//O(m)
inline void Solve() {
    while (m--) {
        register int opt = qread();
        if (opt == 1) {
            register int i = qread();
            blk[pos[i]].val[i - blk[pos[i]].bl + 1] = qread();
            blk[pos[i]].Rebuild();
            for (register int j = pos[i];j <= pos[n];j++) CalcAns(j);
        } else {
            register int k = qread(), ans = 0x3f3f3f3f;
            for (register int i = 1;i <= pos[n];i++) {
                while (blk[i].mx[Min(ans, blk[i].n + 1) - 1] >= k) ans = Min(ans, blk[i].n + 1) - 1;
                // register int l = 0, r = blk[i].n + 1;
                // while (l < r - 1) {
                //     register int mid = l + r >> 1;
                //     if (blk[i].mx[mid] >= k) r = mid;
                //     else l = mid;
                // }
                // if (r <= blk[i].n) ans = Min(ans, r);
            }
            for (register int i = 2;i <= pos[n];i++) {
                register int lpnt = 1, rpnt = 1, orsum1 = 0, orsum2 = 0;
                for (register int j = 1;j <= blk[i - 1].anstop;j++) orsum1 |= (1 << blk[i - 1].ans[j].second);
                orsum2 |= (1 << blk[i].suf[1].second);
                //printf("%d %d\n", blk[i - 1].ans[lpnt].first, blk[i].suf[rpnt].first);
                while (rpnt <= blk[i].suftop && lpnt <= blk[i - 1].anstop) {
                    if (blk[i].suf[rpnt].first - blk[i].bl + 1 >= ans) break;
                    while ((orsum1 | orsum2) >= k && lpnt <= blk[i - 1].anstop) {
                        ans = Min(ans, blk[i].suf[rpnt].first - blk[i - 1].ans[lpnt].first + 1);
                        orsum1 ^= (1 << blk[i - 1].ans[lpnt].second);
                        lpnt++;
                    }
                    while ((orsum1 | orsum2) < k) {
                        rpnt++;
                        if (rpnt > blk[i].suftop) break;
                        orsum2 |= (1 << blk[i].suf[rpnt].second);
                    }
                }
            }
            if (ans == 0x3f3f3f3f) puts("-1");
            else printf("%d\n", ans);
        }
    }
}

int main() {
    Read();
    Prefix();
    Solve();
    #ifndef ONLINE_JUDGE
    while (1);
    #endif
    return 0;
}

by bovine__kebi @ 2020-04-25 20:11:08

又来了


by bovine__kebi @ 2020-04-25 20:11:54

没有火车头不香,加一下火车头和O2说不定能卡过去


by FZzzz @ 2020-04-25 20:13:29

@bovine__kebi 加了指令集了

并且如果这样就能过的话您把 Ynoi 想的太 naive 了


by UnyieldingTrilobite @ 2020-04-25 20:14:01

@bovine__kebi 卡不过,试了


by bovine__kebi @ 2020-04-25 20:14:51

@FZzzz emmmm,可能是我太菜了,毕竟我还有一道没有卡过去的Ynoi。。


by tiger0134 @ 2020-04-25 20:15:44

btd, jbl


by _5011_ @ 2020-04-25 20:15:58

@Mobius ?


by UnyieldingTrilobite @ 2020-04-25 20:17:48

@Zephyr_ 建议重构

我有预感,你删了封装就能过了


by _5011_ @ 2020-04-25 20:19:35

@return20071007 但是题解里面都是封装的啊(


by momo5440 @ 2020-04-25 20:28:58

听大佬说好像把块的大小设成2的倍数会更快


| 下一页