제출 #147155

#제출 시각아이디문제언어결과실행 시간메모리
147155jh05013운세 보기 2 (JOI14_fortune_telling2)C++17
100 / 100
1323 ms47404 KiB
#include <bits/stdc++.h>
#define dbgv(v) {for(auto x:v)cout<<x<<' ';cout<<'\n';}
#define entire(v) v.begin(),v.end()
typedef long long ll;
using namespace std;
void OJize(){
    cin.tie(NULL); ios_base::sync_with_stdio(false);
    #ifdef jh
    freopen("input.txt", "r", stdin);
    #endif
}

// 0-indexed
template <typename T>
struct Segtree{
    T id = -2147483647;
    T combine(T a, T b){
        return max(a, b);
    }
    
    int n; vector<T> arr;
    Segtree(int sz): n{1} {
        while(n < sz) n<<=1;
        arr.resize(n*2);
    }
    void update(int i, T val){
        for(arr[i+=n] = val; i > 1; i/= 2) arr[i/2] = combine(arr[i], arr[i^1]);
    }
    T query(int l, int r){
        T resl = id, resr = id;
        for(l+= n, r+= n+1; l < r; l/= 2, r/= 2){
            if(l&1) resl = combine(resl, arr[l++]);
            if(r&1) resr = combine(resr, arr[--r]);
        }
        return combine(resl, resr);
    }
};

// 0-indexed
template <typename T>
struct Fenwick{
    int n; vector<T> arr;
    Fenwick(int n): n{n}, arr{vector<T>(n)} {}
    void construct(vector<T>& A){
        for(int i=0; i<n; i++) arr[i] = A[i];
        for(int i=0; i<n; i++) if((i|(i+1)) < n) arr[i|(i+1)]+= arr[i];
    }
    void update(int i, T val){
        while(i < n) arr[i]+= val, i |= i+1;
    }
    T getsum(int i){
        T res = 0;
        while(i >= 0) res+= arr[i], i = (i&(i+1))-1;
        return res;
    }
    T intersum(int i, int j){
        return i? (getsum(j) - getsum(i-1)) : getsum(j);
    }
};

/*
 * Treat each card individually, wlog a<b. (if a=b, trivial; if a>b, flip once.)
 * each operation x is either
 *   1. x < a: never flip
 *   2. a <= x < b: set to "flipped"
 *   3. b <= x: always flip
 * so we need to find the last occurrence of a<=x<b, then count the number of b<=x after that point.
 * last occurrence: max segtree
 * count b<=x after some point: offline sum segtree
 */

int main(){OJize();
    // Input and compression
    int n, k; cin>>n>>k;
    vector<tuple<int, int, int>> card(n); // max(a,b), a, b, index 0-i
    vector<pair<int, int>> query(k);           // x, index 1-i
    map<int, int> com;
    for(int i=0; i<n; i++){
        int a, b; cin>>a>>b;
        card[i] = make_tuple(-max(a, b), a, b);
        com[a] = com[b] = 0;
    }
    for(int i=0; i<k; i++) cin>>query[i].first, query[i].second = i+1, com[query[i].first] = 0;
    int i = 0;
    for(auto it = com.begin(); it != com.end(); it++) it->second = i++;
    sort(entire(card));
    sort(entire(query));
    
    // Segtrees
    Segtree<int> maxst(com.size()); // last index of query x, compressed, 1-i
    for(auto &xi: query) maxst.update(com[xi.first], xi.second);
    Fenwick<int> F(k+1); // current occurrence of large query at i, 1-i
    
    // Computation
    ll ans = 0;
    int CI = k-1;
    for(auto& tup: card){
        // Get compressed a and b
        int mab, ra, rb; tie(mab,ra,rb) = tup;
        if(ra == rb){ans+= ra; continue;}
        int a = com[ra], b = com[rb];
        if(a > b) swap(a, b);
        
        // Update large-number queries
        while(CI >= 0 && query[CI].first >= -mab){
            F.update(query[CI].second, 1);
            CI--;
        }
        
        // Count flips
        int last = maxst.query(a, b-1), flip = F.intersum(last, F.n-1) % 2, val;
        if(last == 0) val = flip? rb : ra;
        else val = ((ra>rb)^flip)? ra : rb;
        ans+= val;
        //cout <<ra<<' '<<rb<<" -> "<<a<<' '<<b<<" -> "<<last<<" last; "<<flip<<" flips; "<<val<<'\n';
    }
    
    cout << ans;
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...