Submission #398706

#TimeUsernameProblemLanguageResultExecution timeMemory
398706ChrisTEvent Hopping 2 (JOI21_event2)C++17
100 / 100
231 ms25964 KiB
#include <bits/stdc++.h> using namespace std; const int MN = 2e5 + 5, MOD = 1e9 + 7, LOG = 17; int dp[MN], bit[MN], to[MN], p[MN][LOG]; vector<int> withDp[MN]; void update (int i, int v) { for (;i<MN;i+=i&-i) bit[i] = max(bit[i],v); } int query (int i) { int ret = 0; for (;i>0;i^=i&-i) ret = max(ret,bit[i]); return ret; } vector<int> xs; int getx (int x) {return lower_bound(xs.begin(),xs.end(),x) - xs.begin() + 1;} int main () { int n,k; scanf ("%d %d",&n,&k); vector<array<int,3>> segs(n+1); vector<array<int,2>> og(n+1); for (int i = 1; i <= n; i++) { auto &[l,r,idx] = segs[i]; idx = i; scanf ("%d %d",&l,&r); og[i] = {l,r}; xs.push_back(l); xs.push_back(r); } xs.push_back(0); xs.push_back(MOD); segs.push_back({0,0,n+1}); segs.push_back({MOD,MOD,n+2}); n += 2; sort(xs.begin(),xs.end()); xs.erase(unique(xs.begin(),xs.end()),xs.end()); sort(segs.begin()+1,segs.end()); for (int i = 1; i <= n; i++) { auto &[l,r,idx] = segs[i]; l = getx(l); r = getx(r); to[idx] = i; dp[i] = query(l) + 1; update(r,dp[i]); withDp[dp[i]].push_back(i); } int mx = *max_element(dp+1,dp+1+n); if (mx - 2 < k) return !printf ("-1\n"); auto get = [&] (int v, int x) { //l[i] >= x int low = 0, high = (int)withDp[v].size() - 1, mid, ans = -1; while (low <= high) { mid = (low + high) / 2; if (segs[withDp[v][mid]][0] >= x) high = (ans = mid) - 1; else low = mid + 1; } return ~ans ? withDp[v][ans] : 0; }; for (int v = mx-1; v >= 1; v--) { int mn = 1e9; for (int j = (int)withDp[v].size() - 1; j >= 0; j--) { int i = withDp[v][j]; mn = min(mn,segs[i][1]); p[i][0] = get(v+1,mn); for (int j = 1; j < LOG; j++) p[i][j] = p[p[i][j-1]][j-1]; } } auto pathLength = [&] (int bef, int j) { int i = lower_bound(segs.begin()+1,segs.end(),array<int,3>{segs[bef][1],-MOD,-MOD}) - segs.begin(); if (dp[i] == dp[j]) return 2; int ret = dp[j] - dp[i]; for (int k = 0; k < LOG; k++) if (ret >> k & 1) i = p[i][k]; return ret + 1 + (i > 0 && i <= j); }; set<int> have = {1,n}; int cur = dp[n] - 2; for (int j = 1; j <= n-2 && (int)have.size() < k + 2; j++) { int i = to[j]; auto it = have.lower_bound(i); int lst = *prev(it), nxt = *it; if (segs[lst][1] > segs[i][0] || segs[i][1] > segs[nxt][0]) continue; int oldGet = pathLength(lst,nxt); int newGet = pathLength(lst,i) + pathLength(i,nxt) - 1; if (cur - oldGet + newGet >= k) { //success printf ("%d\n",j); have.insert(i); cur += newGet - oldGet; } } return 0; }

Compilation message (stderr)

event2.cpp: In function 'int main()':
event2.cpp:19:17: warning: ignoring return value of 'int scanf(const char*, ...)', declared with attribute warn_unused_result [-Wunused-result]
   19 |  int n,k; scanf ("%d %d",&n,&k);
      |           ~~~~~~^~~~~~~~~~~~~~~
event2.cpp:25:9: warning: ignoring return value of 'int scanf(const char*, ...)', declared with attribute warn_unused_result [-Wunused-result]
   25 |   scanf ("%d %d",&l,&r); og[i] = {l,r};
      |   ~~~~~~^~~~~~~~~~~~~~~
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...