求助离谱TLE

P1527 [国家集训队] 矩阵乘法

Daniel1234 @ 2023-11-23 14:36:10

#include<bits/stdc++.h>
using namespace std;
#define B 27
int n, q;
int a[505][505];
set<int>st;
unordered_map<int, int>mp;
// int len;
int ord[250005];
int ord_[250005];
vector<int>t[505][505], h[505][505];
int s[4][B*B+5];
int lens[4];
int hh[505][505];
int tong[B*B+5];
vector<int> ordd[505][505];
bitset<B*B+1>bit;
bitset<250005>bitn;
int tt[250005];
inline void add(int op, int x, int y){
    lens[op] = 0;
    if(x%B==0||y%B==0)return;
    memset(tong, 0, sizeof(tong));
    int ii = x / B * B + 1, jj = y / B * B + 1;
    for(int i = ii; i <= x; ++i){
        for(int j = jj; j <= y; ++j){
            tong[hh[i][j]]++;
            bit[hh[i][j]] = 1;
        }
    }
    for(int i = bit._Find_first(); i != bit.size(); i = bit._Find_next(i)){
        while(tong[i]--)s[op][++lens[op]] = ordd[ii][jj][i];
        bit[i] = 0;
    }
}
inline int find(int op, int mx){
    int l = 1, r = lens[op], ans = 0;
    while(l <= r){
        int mid = (l + r) / 2;
        if(s[op][mid] <= mx)ans = mid, l = mid + 1;
        else r = mid - 1;
    }
    return ans;
}
inline int get_(int x, int y, int mx){
    int l = 0, r = t[x][y].size() - 1, ans = -1;
    while(l <= r){
        int mid = l+r>>1;
        if(t[x][y][mid] <= mx)ans = mid, l = mid + 1;
        else r = mid - 1;
    }
    return ans+1;
}
inline int get1(int x, int y, int mx){
    int l = 0, r = h[x][y].size() - 1, ans = -1;
    while(l <= r){
        int mid = l+r>>1;
        if(h[x][y][mid] <= mx)ans = mid, l = mid + 1;
        else r = mid - 1;
    }
    return ans + 1;
}
inline int get(int x, int y, int mx){
    int ans = get_(x/B*B, y/B*B, mx);
    if(y%B!=0){
        int nowx = x / B * B;
        while(nowx){
            ans += get1(nowx, y, mx);
            nowx -= B;
        }
    }
    if(x%B!=0){
        int nowy = y / B * B;
        while(nowy){
            ans += get1(x, nowy, mx);
            nowy -= B;
        }
    }
    for(int i = x/B*B+1; i <= x; ++i){
        for(int j = y/B*B+1; j <= y; ++j){
            if(a[i][j] <= mx)ans++;
        }
    }
    return ans;
}
inline int check(int x, int y, int x_, int y_, int mx){
    int ans = find(0, mx) - find(1, mx) - find(2, mx) + find(3, mx);
    ans += get(x_, y_, mx);
    ans -= get(x - 1, y_, mx);
    ans -= get(x_, y - 1, mx);
    ans += get(x - 1, y - 1, mx);
    return ans;
}
int mpp[250005];
bitset<250005>stt;
inline void hsh(int x, int y, int x_, int y_){
    int lenn = 0;
    for(int i = x; i <= x_; ++i){
        for(int j = y; j <= y_; ++j){
            stt[a[i][j]] = 1;
        }
    }
    ordd[x][y].resize(B*B+1);
    for(int to = stt._Find_first(); to != stt.size(); to = stt._Find_next(to)){
        mpp[to] = ++lenn;
        ordd[x][y][lenn] = to;
    }
    stt.reset();
    for(int i = x; i <= x_; ++i){
        for(int j = y; j <= y_; ++j){
            hh[i][j] = mpp[a[i][j]];
        }
    }
}
int read(){
    int s = 0;
    char ch = getchar();
    while(ch < '0' || ch > '9')ch = getchar();
    while('0' <= ch && ch <= '9'){
        s = s * 10 + ch - '0';
        ch = getchar();
    }
    return s;
}
signed main(){
    cin >> n >> q;
    int len = 0;
    for(int i = 1; i <= n; ++i){
        for(int j = 1; j <= n; ++j){
            a[i][j] = read();
            ord[++len] = a[i][j];
        }
    }
    sort(ord + 1, ord + 1 + len);
    int lenn = 0;
    for(int i = 1; i <= len; ++i){
        if(i==1||ord[i] != ord[i - 1]){
            ord_[++lenn] = ord[i];
        }
    }
    for(int i = 1; i <= n; ++i){
        for(int j = 1; j <= n; ++j){
            int l = 1, r = lenn, sa;
            while(l <= r){
                int mid = l+r>>1;
                if(ord_[mid] <= a[i][j])sa = mid, l = mid + 1;
                else r = mid - 1;
            }
            a[i][j] = sa;
        }
    }
    for(int i = B; i <= n; i += B){
        for(int j = B; j <= n; j += B){
            int ll = 0;
            t[i][j].resize(i*j);
            memset(tt, 0, sizeof(tt));
            for(int x = 1; x <= i; ++x){
                for(int y = 1; y <= j; ++y){
                    tt[a[x][y]]++;
                    bitn[a[x][y]] = 1;
                }
            }
            for(int k = bitn._Find_first(); k != bitn.size(); k = bitn._Find_next(k)){
                while(tt[k]--){
                    t[i][j][ll++] = k;
                }
                bitn[k] = 0;
            }
        }
    }
    for(int i = 1; i <= n; i += B){
        for(int j = 1; j <= n; j += B){
            int x = min(n,i+B-1);
            int y = min(n,j+B-1);
            hsh(i, j, x, y);
        }
    }
    for(int i = B; i <= n; i += B){
        for(int j = 1; j <= n; ++j){
            if(j%B==0)continue;
            int ii = (i-1) / B * B + 1;
            int jj = (j-1) / B * B + 1;
            h[i][j].resize((i-ii+1)*(j-jj+1));
            int ll = 0;
            for(int x = ii; x <= i; ++x){
                for(int y = jj; y <= j; ++y){
                    tong[hh[x][y]]++;
                    bit[hh[x][y]] = 1;
                }
            }
            for(int k = bit._Find_first(); k != bit.size(); k = bit._Find_next(k)){
                while(tong[k]--)h[i][j][ll++] = ordd[ii][jj][k];
                tong[k]++;
                bit[k] = 0;
            }
        }
    }
    for(int i = 1; i <= n; i++){
        if(i%B==0)continue;
        for(int j = B; j <= n; j += B){
            int ii = (i-1) / B * B + 1;
            int jj = (j-1) / B * B + 1;
            h[i][j].resize((i-ii+1)*(j-jj+1));
            int ll = 0;
            for(int x = ii; x <= i; ++x){
                for(int y = jj; y <= j; ++y){
                    tong[hh[x][y]]++;
                    bit[hh[x][y]] = 1;
                }
            }
            for(int k = bit._Find_first(); k != bit.size(); k = bit._Find_next(k)){
                while(tong[k]--)h[i][j][ll++] = ordd[ii][jj][k];
                tong[k]++;
                bit[k] = 0;
            }
        }
    }
    while(q--){
        int x, y, x_, y_, k;
        x = read();
        y = read();
        x_ = read();
        y_ = read();
        k = read();
        add(0, x_, y_);
        add(1, x - 1, y_);
        add(2, x_, y - 1);
        add(3, x - 1, y - 1);
        int l = 1, r = lenn, ans=1;
        while(l <= r){
            int mid = l+r>>1;
            if(check(x, y, x_, y_, mid) >= k){
                ans = mid;
                r = mid - 1;
            }else{
                l = mid + 1;
            }
        }
        // printf("%d\n",1);
        printf("%d\n",ans);
    }
    return 0;
}

RT,最后的printf(”1“)不会T,但输出ans就T了,这是为什么呢?((


by One_JuRuo @ 2023-11-23 14:41:53

@Daniel1234 输出 1 不会 T,我猜测是 WA 了评测机就直接结束了,所以不会 T,所以可能是你复杂度本身有问题?(题和代码都没仔细看


by Daniel1234 @ 2023-11-23 14:43:35

@One_JuRuo ok,我懂了,thx


by Daniel1234 @ 2023-11-23 14:47:43

@One_JuRuo 遗憾的是,输出ans/2也T了((


by One_JuRuo @ 2023-11-23 14:51:39

@Daniel1234 不道啊qwq,可能是输出 ans 被卡常了?你可以试试快输


by Daniel1234 @ 2023-11-23 14:53:43

@One_JuRuo ok,我再卡卡((


by Cczzyy20150005 @ 2023-11-23 14:58:52

可能是你开了O2的原因?


by Daniel1234 @ 2023-11-23 15:53:21

@Cczzyy20150005 sry,没看到,我重写了(


by Daniel1234 @ 2023-11-23 15:53:57

@Cczzyy20150005 待会儿试试不开O2能不能过((


by Daniel1234 @ 2023-11-23 17:15:37

@One_JuRuo 不是被卡常了,是复杂度假了,lg评测机还能跑出WA??((


by Daniel1234 @ 2023-11-23 17:15:54

有点牛的


| 下一页