Submission #424658

#TimeUsernameProblemLanguageResultExecution timeMemory
42465879brueTeams (IOI15_teams)C++14
100 / 100
2732 ms179224 KiB
#include <bits/stdc++.h>
#include "teams.h"

using namespace std;

typedef long long ll;
const ll D = 1000000000;

struct segTree{
    vector<ll> tree[2000002];

    void init(int i, int l, int r){
        if(l==r){
            sort(tree[i].begin(), tree[i].end());
            return;
        }
        int m = (l+r)>>1;
        init(i*2, l, m);
        init(i*2+1, m+1, r);
        tree[i].resize((int)tree[i*2].size() + (int)tree[i*2+1].size());
        merge(tree[i*2].begin(), tree[i*2].end(), tree[i*2+1].begin(), tree[i*2+1].end(), tree[i].begin());
    }

    void addPoint(int i, int l, int r, int x, ll y){
        if(l==r){
            tree[i].push_back(y);
            return;
        }
        int m = (l+r)>>1;
        if(x <= m) addPoint(i*2, l, m, x, y);
        else addPoint(i*2+1, m+1, r, x, y);
    }

    int query(int i, int l, int r, int s, int e, ll vl, ll vr){
        if(r<s || e<l) return 0;
        if(s<=l && r<=e){
            return upper_bound(tree[i].begin(), tree[i].end(), vr) - lower_bound(tree[i].begin(), tree[i].end(), vl);
        }
        int m = (l+r)>>1;
        return query(i*2, l, m, s, e, vl, vr) + query(i*2+1, m+1, r, s, e, vl, vr);
    }

    pair<int, int> findLim(int i, int l, int r, int x, ll s, ll e, int &lim){
        if(l==r){
            int tret = upper_bound(tree[i].begin(), tree[i].end(), e) - lower_bound(tree[i].begin(), tree[i].end(), s);
            if(tret <= lim){
                lim -= tret;
                return make_pair(-1, -1);
            }
            return make_pair(l-1, lim);
        }
        int m = (l+r)>>1;
        if(x>m) return findLim(i*2+1, m+1, r, x, s, e, lim);

        if(x <= l){
            int tret = upper_bound(tree[i].begin(), tree[i].end(), e) - lower_bound(tree[i].begin(), tree[i].end(), s);
            if(tret <= lim){
                lim -= tret;
                return make_pair(-1, -1);
            }
        }

        auto tmp = findLim(i*2, l, m, x, s, e, lim);
        if(tmp.first >= 0) return tmp;
        return findLim(i*2+1, m+1, r, x, s, e, lim);
    }
} tree;
vector<ll> occ[500002];

int n;
pair<ll, int> p[500002];

void init(int N, int A[], int B[]){
    n = N;
    for(int i=0; i<n; i++){
        p[i] = make_pair(D*A[i] + i, B[i]);
        occ[p[i].second].push_back(p[i].first);
        tree.addPoint(1, 1, n, p[i].second, p[i].first);
    }
    tree.init(1, 1, n);

    for(int i=1; i<=n; i++) sort(occ[i].begin(), occ[i].end());
}

int k;
int arr[200002];
stack<pair<ll, int> > stk;

int can(int M, int K[]){
    k = M;
    for(int i=1; i<=k; i++) arr[i] = K[i-1];
    sort(arr+1, arr+k+1);

    while(!stk.empty()) stk.pop();
    stk.push(make_pair(0, n));

    for(int i=1; i<=k; i++){
        int x = arr[i], lim = arr[i];
        while(i<k && arr[i] == arr[i+1]){
            i++;
            x += arr[i];
            if(x>n) return false;
        }

        while(!stk.empty() && stk.top().second < arr[i]) stk.pop();

        while(!stk.empty()){
            pair<ll, int> tmp = stk.top();
            int ret = tree.query(1, 1, n, lim, tmp.second, tmp.first+1, D*arr[i]+(D-1));
            if(ret > x) break;
            stk.pop();
            x -= ret;
            lim = tmp.second+1;
        }

        if(stk.empty()){
            if(x) return false;
            stk.push(make_pair(D*arr[i]+(D-1), n));
            continue;
        }

        pair<ll, int> p = stk.top();
        pair<int, int> tmp = tree.findLim(1, 1, n, lim, p.first+1, D*arr[i]+(D-1), x);
        int bx = tmp.first;

        if(x){
            auto it = lower_bound(occ[bx+1].begin(), occ[bx+1].end(), p.first+1) + (x-1);
            if(stk.top().second == bx+1) stk.pop();
            stk.push(make_pair(*it, bx+1));
        }
        if(stk.top().second == bx) stk.pop();
        stk.push(make_pair(D*arr[i]+(D-1), bx));
    }

    return true;
}

Compilation message (stderr)

teams.cpp: In member function 'int segTree::query(int, int, int, int, int, ll, ll)':
teams.cpp:37:68: warning: conversion from '__gnu_cxx::__normal_iterator<long long int*, std::vector<long long int> >::difference_type' {aka 'long int'} to 'int' may change value [-Wconversion]
   37 |             return upper_bound(tree[i].begin(), tree[i].end(), vr) - lower_bound(tree[i].begin(), tree[i].end(), vl);
      |                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
teams.cpp: In member function 'std::pair<int, int> segTree::findLim(int, int, int, int, ll, ll, int&)':
teams.cpp:45:71: warning: conversion from '__gnu_cxx::__normal_iterator<long long int*, std::vector<long long int> >::difference_type' {aka 'long int'} to 'int' may change value [-Wconversion]
   45 |             int tret = upper_bound(tree[i].begin(), tree[i].end(), e) - lower_bound(tree[i].begin(), tree[i].end(), s);
      |                        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
teams.cpp:56:71: warning: conversion from '__gnu_cxx::__normal_iterator<long long int*, std::vector<long long int> >::difference_type' {aka 'long int'} to 'int' may change value [-Wconversion]
   56 |             int tret = upper_bound(tree[i].begin(), tree[i].end(), e) - lower_bound(tree[i].begin(), tree[i].end(), s);
      |                        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
teams.cpp: In function 'int can(int, int*)':
teams.cpp:122:23: warning: declaration of 'p' shadows a global declaration [-Wshadow]
  122 |         pair<ll, int> p = stk.top();
      |                       ^
teams.cpp:71:15: note: shadowed declaration is here
   71 | pair<ll, int> p[500002];
      |               ^
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...