Submission #774922

#TimeUsernameProblemLanguageResultExecution timeMemory
774922ngraceTeams (IOI15_teams)C++14
77 / 100
4108 ms409948 KiB
#include "teams.h" #include <bits/stdc++.h> using namespace std; #define v vector #define ll long long #define ii pair<int,int> #define fi first #define se second struct node{ ll l; ll r; int sum; }; ll nodecnt=0; v<node> nodes; ll newNode(ll l, ll r){ ll ndc = nodecnt++; nodes.push_back(node()); nodes[ndc].l=l; nodes[ndc].r=r; nodes[ndc].sum = nodes[nodes[ndc].l].sum + nodes[nodes[ndc].r].sum; return ndc; } ll build(int l, int r){ if(l==r){ nodes.push_back(node()); nodes[nodecnt].l = -1; nodes[nodecnt].r = -1; nodes[nodecnt].sum=0; return nodecnt++; } int m=(l+r)/2; return newNode(build(l, m), build(m+1, r)); } ll update(ll cur, int l, int r, int tar){ if(l==r) { nodes.push_back(node()); nodes[nodecnt].l = -1; nodes[nodecnt].r = -1; nodes[nodecnt].sum=nodes[cur].sum+1; return nodecnt++; } int m=(l+r)/2; if(tar<=m){ return newNode(update(nodes[cur].l, l, m, tar), nodes[cur].r); } return newNode(nodes[cur].l, update(nodes[cur].r, m+1, r, tar)); } int query(ll cur, int l, int r, int ql){ if(ql<=l) return nodes[cur].sum; int m=(l+r)/2, ret=0; if(ql<=m) ret += query(nodes[cur].l, l, m, ql); ret += query(nodes[cur].r, m+1, r, ql); return ret; } int binSearchQuery(ll curl, ll curr, int l, int r, int num){ //returns last place where num<amount holds if(l==r) return l; int m=(l+r)/2; int amount = nodes[nodes[curr].r].sum - nodes[nodes[curl].r].sum; if(num >= amount) return binSearchQuery(nodes[curl].l, nodes[curr].l, l,m, num - amount); return binSearchQuery(nodes[curl].r, nodes[curr].r, m+1, r, num); } int n; v<ii> points; v<ll> roots; int getRect(int x1, int x2, int y){ ii p1 = {x1, -1}, p2 = {x2+1, -1}; ll ind1 = distance(points.begin(), lower_bound(points.begin(), points.end(), p1)); ll ind2 = distance(points.begin(), lower_bound(points.begin(), points.end(), p2)); return query(roots[ind2], 1, n, y) - query(roots[ind1], 1, n, y); } int getSplit(int x1, int x2, int num){ ii p1 = {x1, -1}, p2 = {x2+1, -1}; ll ind1 = distance(points.begin(), lower_bound(points.begin(), points.end(), p1)); ll ind2 = distance(points.begin(), lower_bound(points.begin(), points.end(), p2)); return binSearchQuery(roots[ind1], roots[ind2], 1, n, num) + 1;//the first place where the suffix sum is >= num } void init(int N, int A[], int B[]) { n=N; for(int i=0; i<n; i++) points.push_back({A[i], B[i]}); roots.push_back(build(1,n)); sort(points.begin(), points.end()); for(ii it:points) roots.push_back(update(roots.back(), 1, n, it.se)); } int cnt=0; int can(int M, int K[]) { sort(K, K+M); if(M>400){ priority_queue<ii> pq; int j=0; for(int i=0; i<M; i++){ while(j<n && points[j].fi<=K[i]){ pq.push({-points[j].se, points[j].fi}); j++; } while(pq.size()>0 && -pq.top().fi<K[i]) pq.pop(); if((int)pq.size()<K[i]) return 0; for(int k=0; k<K[i]; k++) pq.pop(); } return 1; } v<int> dp(M); set<int> opt; priority_queue<pair<int,ii>> pq; for(int i=0; i<M; i++){ dp[i] = getRect(0, K[i], K[i]) - K[i]; while(pq.size()>0 && pq.top().fi<=K[i]){ int j1=pq.top().se.fi; int j2=pq.top().se.se; pq.pop(); if(opt.find(j1)==opt.end() || opt.find(j2)==opt.end()) continue; opt.erase(j2); } if(i){ auto it=opt.end(); it--; int j=*it; dp[i] = min(dp[i], dp[j] + (K[i]==K[j] ? 0 : getRect(K[j]+1, K[i], K[i])) - K[i]); } for(int j=0; j<i; j++){ if(M>100) break; dp[i] = min(dp[i], dp[j] + (K[i]==K[j] ? 0 : getRect(K[j]+1, K[i], K[i])) - K[i]); } if(dp[i]<0) return 0; opt.insert(i); if(i){ auto it = opt.end(); it--; it--; int j1=*it; int j2=i; int k = (K[j1]==K[j2]) ? 0 : getSplit(K[j1]+1, K[j2], dp[j2]-dp[j1]); if(K[j1]==K[j2]) k= (dp[j2] - dp[j1] < 0) ? K[M-1]+1 : K[j2]+1; pq.push({k, {j1,j2}}); } } return 1; }
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...