제출 #1345469

#제출 시각아이디문제언어결과실행 시간메모리
1345469ahmedqassem_Klasika (COCI20_klasika)C++20
33 / 110
584 ms589824 KiB
// Author : AhmedQassem_
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using ld = long double;
using ull = unsigned long long;

#define endl '\n'
//#define int ll
#define ep cout << fixed << setprecision(12)
#define all(x) (x).begin(), (x).end()
#define allr(x) (x).rbegin(), (x).rend()

const int INF = 0x3f3f3f3f;
const ll LINF = 0x3f3f3f3f3f3f3f3f;
const int mod = 1e9 + 7;
//const int mod = 998244353;
const ld PI = acosl(-1.0L);
int dx[] = {0,0,1,-1};
int dy[] = {1,-1,0,0};

int gcd(int a, int b) { return b ? gcd(b, a % b) : a; }
int lcm(int a, int b) { return a / gcd(a, b) * b; }


void fileio() {
    #ifndef ONLINE_JUDGE
     freopen("input.txt", "r", stdin);
     freopen("output.txt", "w", stdout);
    #endif
}

void fastio() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);
}

const int N = 2e5+5 ,M = 23;
vector<vector<pair<int,int>>>adj(N);
vector<int>tin(N) , tout(N) , val(N);
int timer = 0;
void dfs(int u , int cnt = 0, int p = -1){
    tin[u] = ++ timer;
    val[u] = cnt;
    for(auto[v,w] : adj[u]){
        if(v != p){
            dfs(v,cnt ^ w , u);
        }
    }
    tout[u] = timer;
}
struct BinaryTrie {
    static const int MAX_BIT = 32; // adjust for the max number of bits needed

    struct Node {
        int nxt[2]; // next nodes for bit 0 and 1
        int cnt;    // how many numbers pass through this node
        int end;    // how many numbers end at this node
        Node() { nxt[0] = nxt[1] = 0; cnt = end = 0; }
    };

    vector<Node> tr;

    BinaryTrie(int reserve_nodes = 0) { if(reserve_nodes) tr.reserve(reserve_nodes); tr.push_back(Node()); } // constructor

    int add_node() { tr.push_back(Node()); return (int)tr.size() - 1; } // create new node

    int size() const { return tr[0].cnt; } // total numbers
    int nodes() const { return (int)tr.size(); } // total nodes
    bool empty() const { return tr[0].cnt == 0; } // is trie empty
    void clear() { tr.clear(); tr.push_back(Node()); } // reset trie

    void insert(unsigned long long x) { // insert number x
        int u = 0; tr[u].cnt++;
        for(int i = MAX_BIT; i >= 0; --i) {
            int b = (x >> i) & 1ULL;
            if(!tr[u].nxt[b]) tr[u].nxt[b] = add_node();
            u = tr[u].nxt[b]; tr[u].cnt++;
        }
        tr[u].end++;
    }

    int count_exact(unsigned long long x) const { // occurrences of x
        int u = 0;
        for(int i = MAX_BIT; i >= 0; --i) {
            int b = (x >> i) & 1ULL;
            if(!tr[u].nxt[b]) return 0;
            u = tr[u].nxt[b];
        }
        return tr[u].end;
    }

    bool contains(unsigned long long x) const { return count_exact(x) > 0; } // check if x exists

    bool erase(unsigned long long x) { // remove one occurrence of x
        if(count_exact(x) == 0) return false;
        int u = 0; tr[u].cnt--;
        for(int i = MAX_BIT; i >= 0; --i) {
            int b = (x >> i) & 1ULL;
            u = tr[u].nxt[b]; tr[u].cnt--;
        }
        tr[u].end--; return true;
    }

    unsigned long long max_xor_value(unsigned long long x) const { // max XOR with x
        if(empty()) return 0;
        int u = 0; unsigned long long res = 0;
        for(int i = MAX_BIT; i >= 0; --i) {
            int b = (x >> i) & 1ULL, want = b ^ 1;
            if(tr[u].nxt[want] && tr[tr[u].nxt[want]].cnt > 0) { res |= (1ULL << i); u = tr[u].nxt[want]; }
            else u = tr[u].nxt[b];
        }
        return res;
    }

    unsigned long long min_xor_value(unsigned long long x) const { // min XOR with x
        if(empty()) return 0;
        int u = 0; unsigned long long res = 0;
        for(int i = MAX_BIT; i >= 0; --i) {
            int b = (x >> i) & 1ULL;
            if(tr[u].nxt[b] && tr[tr[u].nxt[b]].cnt > 0) u = tr[u].nxt[b];
            else { res |= (1ULL << i); u = tr[u].nxt[b ^ 1]; }
        }
        return res;
    }

    unsigned long long max_xor_number(unsigned long long x) const { // number giving max XOR with x
        if(empty()) return ULLONG_MAX;
        int u = 0; unsigned long long y = 0;
        for(int i = MAX_BIT; i >= 0; --i) {
            int b = (x >> i) & 1ULL, want = b ^ 1;
            if(tr[u].nxt[want] && tr[tr[u].nxt[want]].cnt > 0) { y |= (1ULL << i); u = tr[u].nxt[want]; }
            else { y |= (unsigned long long)b << i; u = tr[u].nxt[b]; }
        }
        return y;
    }

    unsigned long long min_xor_number(unsigned long long x) const { // number giving min XOR with x
        if(empty()) return ULLONG_MAX;
        int u = 0; unsigned long long y = 0;
        for(int i = MAX_BIT; i >= 0; --i) {
            int b = (x >> i) & 1ULL;
            if(tr[u].nxt[b] && tr[tr[u].nxt[b]].cnt > 0) { y |= (unsigned long long)b << i; u = tr[u].nxt[b]; }
            else { y |= (unsigned long long)(b ^ 1) << i; u = tr[u].nxt[b ^ 1]; }
        }
        return y;
    }

    unsigned long long kth_smallest(long long k) const { // kth smallest number
        if(k <= 0 || k > tr[0].cnt) return ULLONG_MAX;
        int u = 0; unsigned long long res = 0;
        for(int i = MAX_BIT; i >= 0; --i) {
            int left = tr[u].nxt[0], left_cnt = left ? tr[left].cnt : 0;
            if(k <= left_cnt) u = left;
            else { k -= left_cnt; res |= (1ULL << i); u = tr[u].nxt[1]; }
        }
        return res;
    }

    long long count_less_than(unsigned long long x) const { // count numbers < x
        long long ans = 0; int u = 0;
        for(int i = MAX_BIT; i >= 0; --i) {
            int b = (x >> i) & 1ULL;
            if(b == 1) { int left = tr[u].nxt[0]; if(left) ans += tr[left].cnt; u = tr[u].nxt[1]; }
            else u = tr[u].nxt[0];
            if(!u) break;
        }
        return ans;
    }

    long long count_xor_less_than(unsigned long long x, unsigned long long k) const { // count numbers y: (x^y) < k
        long long ans = 0; int u = 0;
        for(int i = MAX_BIT; i >= 0; --i) {
            int xb = (x >> i) & 1ULL, kb = (k >> i) & 1ULL;
            if(!u) break;
            if(kb == 1) { int same = tr[u].nxt[xb]; if(same) ans += tr[same].cnt; u = tr[u].nxt[xb ^ 1]; }
            else u = tr[u].nxt[xb];
        }
        return ans;
    }

    unsigned long long lower_bound_value(unsigned long long x) const { // first number >= x
        long long rk = count_less_than(x) + 1;
        if(rk > tr[0].cnt) return ULLONG_MAX;
        return kth_smallest(rk);
    }

    unsigned long long upper_bound_value(unsigned long long x) const { // first number > x
        if(x == ULLONG_MAX) return ULLONG_MAX;
        long long rk = count_less_than(x + 1) + 1;
        if(rk > tr[0].cnt) return ULLONG_MAX;
        return kth_smallest(rk);
    }

};
struct Node
{
    BinaryTrie val;
    Node() {
        val = BinaryTrie();
    }
    Node(int x) {
        val = BinaryTrie();
        val.insert(x);
    }
    void change(int x) {
        val.erase(x);
    }
};
struct SegTree
{
    int tree_size;
    vector<Node> SegData;
    SegTree(int n)
    {
        tree_size = 1;
        while (tree_size < n) tree_size *= 2;
        SegData.assign(2 * tree_size, Node());
    }
    // Node merge(Node& lf, Node& ri)
    // {
    //     Node ret = Node();
    //     return ret;
    // }
    void init(vector<int>& arr, int ni, int lx, int rx)
    {
        SegData[ni] = Node();
        for(int i = lx ; i < rx and i < arr.size() ; i++){
            SegData[ni].val.insert(arr[i]);
        }
        if(rx - lx == 1)return;
        int mid = (rx + lx) / 2;
        init(arr, 2 * ni + 1, lx, mid);
        init(arr, 2 * ni + 2, mid, rx);
        //SegData[ni] = merge(SegData[2 * ni + 1], SegData[2 * ni + 2]);
    }
    void init(vector<int>& arr) { init(arr, 0, 0, tree_size); }
    void set(int idx, int val, int ni, int lx, int rx)
    {
        if (rx - lx == 1)
        {
            SegData[ni].change(val); return;
        }
        int mid = (rx + lx) / 2;
        if (idx < mid)
        {
            set(idx, val, 2 * ni + 1, lx, mid);
            SegData[ni].change(val);
        }
        else
        {
            set(idx, val, 2 * ni + 2, mid, rx);
            SegData[ni].change(val);

        }
        //SegData[ni] = merge(SegData[2 * ni + 1], SegData[2 * ni + 2]);
    }
    void set(int idx, int val)
    {
        set(idx, val, 0, 0, tree_size);
    }
    int get(int l, int r, int val, int ni, int lx, int rx)
    {
        if (lx >= l && rx <= r) return SegData[ni].val.max_xor_value(val);
        if (lx >= r || rx <= l) return 0;
        int mid = (rx + lx) / 2;
        int lf = get(l, r,val, 2 * ni + 1, lx, mid);
        int ri = get(l, r,val, 2 * ni + 2, mid, rx);
        return max(lf, ri);
    }
    int get(int l, int r , int val) { return get(l, r,val, 0, 0, tree_size); }
};


void Magek() {
    int q; cin >> q;
    deque<array<int,4>>qu;
    int id = 2;
    for(int i = 0 ; i < q ; i++){
        string s;
        int u,v; cin >> s >>  u >> v;
        qu.push_front({s == "Add" , u , v,id});
        if(s == "Add"){
            adj[u].push_back({id , v});
            adj[id++].push_back({u , v});
        }
    }
    vector<int>a(id);
    dfs(1);
    for(int i = 1 ; i < id ; i++){
        a[tin[i]-1] = val[i];
    }
    SegTree tree(id);
    tree.init(a);
    deque<int>ans;
    for(auto& i : qu){
        int t = i[0] , u = i[1] , v = i[2] , idx = i[3];
        if(t == 1){
            tree.set(tin[idx]-1,val[idx]);
        }
        else{
            ans.push_front(tree.get(tin[v]-1 , tout[v] ,val[u]));
        }
    }
    for(int i : ans){
        cout << i << endl;
    }
}

int32_t main() {
    //fileio();
    fastio();
    int t = 1;
    //cin >> t;
    while (t--) Magek();
    return 0;
}

컴파일 시 표준 에러 (stderr) 메시지

klasika.cpp: In function 'void fileio()':
klasika.cpp:28:13: warning: ignoring return value of 'FILE* freopen(const char*, const char*, FILE*)' declared with attribute 'warn_unused_result' [-Wunused-result]
   28 |      freopen("input.txt", "r", stdin);
      |      ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~
klasika.cpp:29:13: warning: ignoring return value of 'FILE* freopen(const char*, const char*, FILE*)' declared with attribute 'warn_unused_result' [-Wunused-result]
   29 |      freopen("output.txt", "w", stdout);
      |      ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...