[TIOJ]1998. 網路遮罩

題目連結:http://tioj.ck.tp.edu.tw/problems/1998

可以把字串處理成數字,先排序左界,二分搜找最後一個小於等於該數字的位置,所有左界小於等於詢問的數字便在此位置的前綴,因此只要維護前綴最大值即可。
#include <bits/stdc++.h>
#define PB push_back
#define F first
#define S second
#define lld long long 
#define jizz cin.tie(0);ios_base::sync_with_stdio(0);
#define endl '\n'
using namespace std;
typedef pair<lld,lld> Pair;
lld tmp,t,p;
string s;
vector<Pair> v;
bool find(lld t){
    int l = 0,r = v.size();
    while(r-l != 1){
        int M = (l+r)/2;
        if(v[M].F > t)r = M;
        else l = M;
    }
    return v[l].F <= t && v[l].S >= t;
}
int main(){jizz
    int n,m;cin >> n >> m;
    for(int i = 0 ; i < n ;i ++){
        cin >>s;
        tmp = 0,t = 0;
        for(int  i = 0 ; i < s.size(); i++){
            if(s[i] == '.')t <<= 8,t += tmp,tmp = 0;
            else if(s[i] >= '0' && s[i] <= '9')tmp *= 10,tmp += s[i]-'0';
            else if(s[i] == '/'){
                t <<= 8,t += tmp,p = i,tmp = 0;
                break;
            }
        }
        for(int j = p+1; j < s.size(); j++)tmp *= 10,tmp += s[j]-'0';
        t >>= (32-tmp);
        lld e = (t << (32-tmp));
        for(int i = 0 ; i <(32-tmp); i++)t <<= 1,t++;
        v.PB({e,t});
    }
    sort(v.begin(),v.end());
    for(int i = 1 ; i < v.size() ; i++)v[i].S = max(v[i].S,v[i-1].S);
    while(m--){
        cin >>s;
        s += '.';
        tmp = 0,t = 0;
        for(int i = 0 ; i < s.length(); i++){
            if(s[i] == '.')t <<= 8,t += tmp,tmp = 0;
            else if(s[i] >= '0' &&s[i] <= '9')tmp *= 10,tmp += s[i]-'0';
        }
        cout << (find(t) ? "TRUE" : "FALSE") << endl;
    }
    return 0;
}


留言

這個網誌中的熱門文章

[TIOJ]1617. [Interactive] 中位數

[TIOJ]1337. 隕石

[TIOJ]1994. 冰塊線