关于这个题最后一个点

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

xqqQwQ_ @ 2023-05-17 21:25:43

已经卡了两个小时了,实在蚌埠住了。

明明别的点都跑的很快,就是最后一个点怎么都卡不过去。

求大佬帮忙

#include<bits/stdc++.h>
#define pb push_back
#define pii pair<int, int>
#define mkp make_pair
#define fi first
#define se second

using namespace std;

const int N = 5e4 + 5;
const int MT = 2001;
const int Bit = 31;
const int inf = 1e9;

#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 read()
{
    char c=getchar();int x=0;bool f=0;
    for(;!isdigit(c);c=getchar())f^=!(c^45);
    for(;isdigit(c);c=getchar())x=(x<<1)+(x<<3)+(c^48);
    if(f)x=-x;return x;
}

void write(int x) {
    if(x <= 9) return putchar(x + '0'), void();
    write(x / 10);
    putchar(x % 10 + '0');
    return;
}

int n, m;
int a[N];
int loc[N], st[N], ed[N];
int maxn[MT][MT], vis[N];
int sss[MT];
int tt[N][32];
vector<pii> pre[MT], suf[MT];
vector<pii> V[N], T, t2;
vector<int> C[N];

int main() {
    n = read(), m = read();
    for(int i = 1; i <= n; ++i) a[i] = read();
    int B = 5 * (int)sqrt(n) + 2, MaxB = 0;
    for(int i = 1; i <= n; ++i) {
        loc[i] = i / B + 1; MaxB = max(MaxB, loc[i]);
        ed[loc[i]] = i;
        if(!st[loc[i]]) st[loc[i]] = i;
    }
    for(int i = 1; i <= MaxB; ++i) {
        int su = 0;
        for(int j = st[i]; j <= ed[i]; ++j) {
            sss[i] |= a[j];
            su |= a[j];
            if(j == st[i]) {
                pre[i].pb(mkp(su, j));
                continue;
            }
            if(su != pre[i].back().fi) pre[i].pb(mkp(su, j));
        }
        su = 0;
        for(int j = ed[i]; j >= st[i]; --j) {
            su |= a[j];
            if(j == ed[i]) {
                suf[i].pb(mkp(su, j));
                continue;
            }
            if(su != suf[i].back().fi) suf[i].pb(mkp(su, j));
        } 
        for(int j = st[i]; j <= ed[i]; ++j) {
            for(int k = 0; k < Bit; ++k) if(a[j] & (1 << k)) V[j].pb(mkp(j, k)), vis[k] = 1, C[j].pb(k);
            if(j != st[i]) {
                for(pii p : V[j - 1]) {
                    if(vis[p.se]) continue;
                    V[j].pb(p);
                }
            }
            int su = 0;
            for(pii p : V[j]) su |= (1 << p.se), maxn[i][j - p.fi + 1] = max(maxn[i][j - p.fi + 1], su); 
            for(int k : C[j]) vis[k] = 0;
        }
        for(int j = 1; j <= ed[i] - st[i] + 2; ++j) maxn[i][j] = max(maxn[i][j], maxn[i][j - 1]);
    }
    for(int i = 1; i <= m; ++i) {
        int opt, x, b;
        opt = read(), x = read();
        if(opt == 1) {
            b = read(); int t = loc[x]; a[x] = b; sss[t] = 0;
            int s1 = st[t], s2 = ed[t]; C[x].clear();
            for(int k = 0; k < Bit; ++k) if(a[x] & (1 << k)) C[x].pb(k);
            int su = 0; pre[t].clear(), suf[t].clear();
            for(int j = 0; j <= s2 - s1 + 2; ++j) maxn[t][j] = 0;
            for(int j = s1; j <= s2; ++j) {
                sss[t] |= a[j];
                su |= a[j];
                if(j == s1) {
                    pre[t].pb(mkp(su, j));
                    continue;
                }
                if(su != pre[t].back().fi) pre[t].pb(mkp(su, j));
            }
            su = 0;
            for(int j = s2; j >= s1; --j) {
                su |= a[j];
                if(j == s2) {
                    suf[t].pb(mkp(su, j));
                    continue;
                }
                if(su != suf[t].back().fi) suf[t].pb(mkp(su, j));
            } 
            for(int j = s1; j <= s2; ++j) {
                V[j].clear();
                int su = 0;
                for(int k : C[j]) su |= (1 << k), V[j].pb(mkp(j, k)), vis[k] = 1;
                maxn[t][1] = max(maxn[t][1], su);
                if(j != s1) {
                    for(pii p : V[j - 1]) {
                        if(vis[p.se]) continue;
                        su |= (1 << p.se); int tmp = j - p.fi + 1;
                        maxn[t][tmp] = max(maxn[t][tmp], su);
                        V[j].pb(p);
                    }
                }
                for(int k : C[j]) vis[k] = 0;
            }
            for(int j = 1; j <= s2 - s1 + 1; ++j) maxn[t][j] = max(maxn[t][j], maxn[t][j - 1]);
        }
        else {
            int minn = inf;
            for(int t = 1; t <= MaxB; ++t) {
                int ll = 1, rr = ed[t] - st[t] + 1, midn, ansn = inf;
                while(ll <= rr) {
                    midn = (ll + rr) >> 1;
                    if(maxn[t][midn] >= x) ansn = midn, rr = midn - 1;
                    else ll = midn + 1;
                } 
                minn = min(minn, ansn);
            }
            T.clear();
            for(int t = 1; t <= MaxB; ++t) {
                t2.clear();
                for(pii p : pre[t]) {
                    if(T.empty()) break;
                    while(T.size() && (T.back().fi | p.fi) >= x) {
                        minn = min(minn, p.se - T[T.size() - 1].se + 1);
                        T.pop_back();
                    }
                }
                int p1 = 0, p2 = 0;
                int SS = T.size();
                for(int j = 0; j < SS; ++j) T[j].fi |= sss[t]; 
                while(p1 < SS && p2 < suf[t].size()) {
                    if(T[p1].fi == suf[t][p2].fi) p1++;
                    else if(T[p1].fi < suf[t][p2].fi) t2.pb(T[p1++]);
                    else t2.pb(suf[t][p2++]);
                }
                while(p1 < SS) t2.pb(T[p1++]);
                while(p2 < suf[t].size()) t2.pb(suf[t][p2++]);
                swap(T, t2);
            }
            (minn == inf ? puts("-1") : (write(minn), putchar('\n'), 0));
        }
    }
    return 0;
}

by xqqQwQ_ @ 2023-05-17 21:38:13

破案了,最后一个点必须把块长开到 < sqrt(n)


by Miraik @ 2023-05-18 07:59:49

最后一个点基本全是修改。


|