Submission #1312352

#TimeUsernameProblemLanguageResultExecution timeMemory
1312352Zbyszek99Examination 2 (JOI24_examination2)C++20
100 / 100
951 ms746620 KiB
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#define ll long long
#define ld long double
#define ull unsigned long long
#define ff first
#define ss second
#define pii pair<int,int>
#define pll pair<long long, long long>
#define vi vector<int>
#define vl vector<long long>
#define pb push_back
#define rep(i, b) for(int i = 0; i < (b); ++i)
#define rep2(i,a,b) for(int i = a; i <= (b); ++i)
#define rep3(i,a,b,c) for(int i = a; i <= (b); i+=c)
#define count_bits(x) __builtin_popcountll((x))
#define all(x) (x).begin(),(x).end()
#define siz(x) (int)(x).size()
#define forall(it,x) for(auto& it:(x))
using namespace __gnu_pbds;
using namespace std;
typedef tree<int, null_type, less<int>, rb_tree_tag,tree_order_statistics_node_update> ordered_set;
//mt19937 mt;void random_start(){mt.seed(chrono::time_point_cast<chrono::milliseconds>(chrono::high_resolution_clock::now()).time_since_epoch().count());}
//ll los(ll a, ll b) {return a + (mt() % (b-a+1));}
const int INF = (1<<18);
const ll INF_L = 1e18+40;
const ll MOD = 1e9+7;

struct node
{
    int l = 0;
    int r = INF-1;
    node* left = NULL;
    node* right = NULL;
    int nxt_one = INF;
    int nxt_zero = 0;
    int push = 0;
    int merges = 0;
    void sons()
    {
        if(left == NULL)
        {
            left = new node;
            left -> l = l;
            left -> r = (l+r)/2;
            left -> nxt_zero = l;
            right = new node;
            right -> l = (l+r)/2+1;
            right -> r = r;
            right -> nxt_zero = (l+r)/2+1;
        }
        if(push)
        {
            swap(left->nxt_one,left->nxt_zero);
            swap(right->nxt_one,right->nxt_zero);
            left->push ^= 1;
            right->push ^= 1;
            push = 0;
        }
    }
    void pull()
    {
        sons();
        nxt_one = min(left->nxt_one,right->nxt_one);
        nxt_zero = min(left->nxt_zero,right->nxt_zero);
    }
    void xor_seg(int l2, int r2)
    {
        if(r < l2 || l > r2) return;
        if(l >= l2 && r <= r2)
        {
            push ^= 1;
            swap(nxt_one,nxt_zero);
            return;
        }
        sons();
        left->xor_seg(l2,r2);
        right->xor_seg(l2,r2);
        pull();
    }
    int get_nxt_zero(int l2)
    {
        if(r < l2) return INF;
        if(l2 <= l) return nxt_zero;
        sons();
        return min(left->get_nxt_zero(l2),right->get_nxt_zero(l2));
    }
    int get_nxt_one(int l2)
    {
        if(r < l2) return INF;
        if(l2 <= l) return nxt_one;
        sons();
        return min(left->get_nxt_one(l2),right->get_nxt_one(l2));
    }
};

vi query_vals;

void set_dp(node& x, int a)
{
    int l = 0;
    int r = siz(query_vals)-1;
    int ans = siz(query_vals);
    while(l <= r)
    {
        int mid = (l+r)/2;
        if(query_vals[mid] >= a)
        {
            ans = mid;
            r = mid-1;
        }
        else
        {
            l = mid+1;
        }
    }
    x.xor_seg(ans,INF);
    x.merges = 1;
}

void not_dp(node& x)
{
    x.xor_seg(0,INF-1);
}

void and_dp(node& x, node& y)
{
    if(x.merges < y.merges) swap(x,y);
    x.merges += y.merges;
    int p = 0;
    while(true)
    {
        p = y.get_nxt_zero(p);
        if(p == INF) break;
        int r = y.get_nxt_one(p)-1;
        while(true)
        {
            int l2 = x.get_nxt_one(p);
            if(l2 > r) break;
            int r2 = min(r,x.get_nxt_zero(l2)-1);
            x.xor_seg(l2,r2);
        }
        p = r+1;
    }
}

void xor_dp(node& x, node& y)
{
    if(x.merges < y.merges) swap(x,y);
    x.merges += y.merges;
    int p = 0;
    while(true)
    {
        p = y.get_nxt_one(p);
        if(p == INF) break;
        int r = y.get_nxt_zero(p)-1;
        x.xor_seg(p,r);
        p = r+1;
    }
}

void or_dp(node& x, node& y)
{
    if(x.merges < y.merges) swap(x,y);
    x.merges += y.merges;
    int p = 0;
    while(true)
    {
        p = y.get_nxt_one(p);
        if(p == INF) break;
        int r = y.get_nxt_zero(p)-1;
        while(true)
        {
            int l2 = x.get_nxt_zero(p);
            if(l2 > r) break;
            int r2 = min(r,x.get_nxt_one(l2)-1);
            x.xor_seg(l2,r2);
        }
        p = r+1;
    }
}

int n;
string s;
int depth[1000001];
int ending[1000001];
int prev_oper[1000001][3];
int prev2[1000003][3];

void rek_depth(int l, int r, int d = 0)
{   
    rep2(i,l,r)
    {
        depth[i] = d;
        if(s[i] == '(')
        {
            depth[ending[i]] = d;
            rek_depth(i+1,ending[i]-1,d+1);
            i = ending[i];
            continue;
        }
    }
}

node rek(int l, int r)
{
    rep(o,3)
    {
        if(prev_oper[r][o] >= l)
        {
            node a1 = rek(l,prev_oper[r][o]-1);
            node a2 = rek(prev_oper[r][o]+1,r);
            if(o == 0) or_dp(a1,a2);
            if(o == 1) xor_dp(a1,a2);
            if(o == 2) and_dp(a1,a2);
            return a1;
        }
    }
    if(s[l] == '!')
    {
        node a = rek(l+1,r);
        not_dp(a);
        return a;
    }
    if(s[l] == '(') return rek(l+1,r-1);
    node a;
    int x = 0;
    rep2(i,l+1,r-1) x += pow(10,r-i-1)*(s[i]-'0');
    set_dp(a,x);
    return a;
}

int main()
{
    ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);
    //random_start();
    int n,q;
    cin >> n >> q >> s;
    vi queries;
    rep(qq,q)
    {
        int x;
        cin >> x;
        queries.pb(x);
        query_vals.pb(x);
    }
    sort(all(query_vals));
    int cur = 0;
    unordered_map<int,int> prev;
    for(int i = n-1; i >= 0; i--)
    {
        if(s[i] == ')')
        {
            cur++;
            prev[cur] = i;
        }
        if(s[i] == '(')
        {
            ending[i] = prev[cur];
            cur--;
        }
    }
    rek_depth(0,n-1);
    rep(d,3) rep(i,n) prev2[i][d] = -1;
    rep(i,n)
    {
        if(s[i] == '|') prev2[depth[i]][0] = i;
        if(s[i] == '^') prev2[depth[i]][1] = i;
        if(s[i] == '&') prev2[depth[i]][2] = i;
        rep(d,3) prev_oper[i][d] = prev2[depth[i]][d];
    }
    node ans_dp = rek(0,n-1);
    forall(it,queries)
    {
        int l = 0;
        int r = q-1;
        int ans = 0;
        while(l <= r)
        {
            int mid = (l+r)/2;
            if(query_vals[mid] >= it)
            {
                ans = mid;
                r = mid-1;
            }
            else
            {
                l = mid+1;
            }
        }
        if(ans_dp.get_nxt_one(ans) == ans) cout << "True\n";
        else cout << "False\n";
    }
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...