Submission #212259

#TimeUsernameProblemLanguageResultExecution timeMemory
212259zscoderHarvest (JOI20_harvest)C++17
100 / 100
4006 ms405008 KiB
#include <bits/stdc++.h> #include <ext/pb_ds/assoc_container.hpp> #include <ext/pb_ds/tree_policy.hpp> #pragma GCC target ("avx2") #pragma GCC optimization ("O3") #pragma GCC optimization ("unroll-loops") using namespace std; using namespace __gnu_pbds; #define fi first #define se second #define mp make_pair #define pb push_back #define fbo find_by_order #define ook order_of_key typedef long long ll; typedef pair<ll,ll> ii; typedef vector<ll> vi; typedef long double ld; typedef tree<ii, null_type, less<ii>, rb_tree_tag, tree_order_statistics_node_update> pbds; typedef tree<int, null_type, less<int>, rb_tree_tag, tree_order_statistics_node_update> pbds2; vi people; vi apple; int timer=0; int to[222222]; ll w[222222]; vector<ll> apples[222222]; int n,m; ll L,C; ll D(ll x, ll y) { if(x<=y) return y-x; return L-(x-y); } vector<vi> cycles; int visited[222222]; int iscyc[222222]; set<int> path; void getcycles(int u) { //cerr<<u<<' '<<visited[u]<<'\n'; if(visited[u]==2) { iscyc[u]=1; cycles.back().pb(u); } path.insert(u); if(visited[to[u]]>0&&path.find(to[u])==path.end()) { visited[u]=1; return ; } if(visited[to[u]]==2) return ; if(visited[to[u]]==1) { if(visited[u]==1) cycles.pb({}); visited[to[u]]=2; getcycles(to[u]); return ; } //unvisited visited[to[u]]=1; getcycles(to[u]); } vi T[222222]; //tree edges pbds* A[222222]; //debug ll shift[222222]; ll ans[222222]; vi adj[222222]; int subsize[222222]; void dfs(int u, int p=-1) { subsize[u]=1; for(int v:adj[u]) { if(iscyc[v]) continue; if(v==p) continue; T[u].pb(v); dfs(v,u); subsize[u]+=subsize[v]; } } vector<pair<ll,int> > queries[222222]; void getA(int u, int p=-1) { //for(ll x:apples[u]) A[u].insert({x,++timer}); //later change to dsu on tree if(T[u].empty()) { A[u] = new pbds; } for(int v:T[u]) { getA(v,u); if(v==T[u][0]) { A[u]=A[v]; shift[u]=shift[v]+w[v]; } else { while(!A[v]->empty()) { ii x = *(A[v]->begin()); A[v]->erase(A[v]->begin()); A[u]->insert({x.fi+shift[v]+w[v]-shift[u],x.se}); } } } for(ll x:apples[u]) A[u]->insert({x-shift[u],++timer}); if(iscyc[u]) return ; for(ii x:queries[u]) { int z = x.se; ll t = x.fi; //cerr<<"HERE "<<z<<' '<<A[u]->order_of_key({t+1-shift[u],-1})<<'\n'; ans[z] = A[u]->order_of_key({t+1-shift[u],-1}); } } ll flr(ll a, ll b) { if(a>=0) return a/b; else return -((abs(a)+b-1)/b); } ll md(ll a, ll b) { a%=b; if(a<0) a+=b; return a; } ll ans2[222222]; struct Fenwick { vector<ll> t; Fenwick(int n) { t.assign(n+1,0); } void reset(int n) { t.assign(n+1, 0); } void update(int p, ll v) { for (; p < (int)t.size(); p += (p&(-p))) t[p] += v; } ll query(int r) //finds [1, r] sum { ll sum = 0; for (; r; r -= (r&(-r))) sum += t[r]; return sum; } ll query(int l, int r) //finds [l, r] sum { if(l == 0) return query(r); return query(r) - query(l-1); } }; pbds2 st[810111]; vi affected; int mx[810111]; void update(int id, int l, int r, int pos, int v) { if(pos>=r||pos<l) return ; if(v>mx[id]) mx[id]=v; affected.pb(id); st[id].insert(v); if(r-l<2) return ; int mid=(l+r)>>1; update(id*2,l,mid,pos,v); update(id*2+1,mid,r,pos,v); } int query(int id, int l, int r, int ql, int qr, int v) //# of elements >= v { if(ql>=r||l>=qr) return 0; if(v>mx[id]) return 0; if(ql<=l&&r<=qr) return st[id].size()-st[id].order_of_key(v); int mid=(l+r)>>1; return query(id*2,l,mid,ql,qr,v)+query(id*2+1,mid,r,ql,qr,v); } int main() { ios_base::sync_with_stdio(0); cin.tie(0); const bool DEBUG=0; srand(12345); for(int cc=1;;cc++) { n=m=L=C=0; if(!DEBUG) cin>>n>>m>>L>>C; people.clear(); apple.clear(); if(DEBUG) { while(n==0) { people.clear(); apple.clear(); L=20; int l1 = rand()%1000; int l2 = rand()%1000; if(l1>l2) swap(l1,l2); for(int i=0;i<10;i++) { int p = rand()%1000; if(p<=l1) people.pb(i); else if(p<=l2) apple.pb(i); } n=people.size(); m=apple.size(); C=rand()%10+1; } } if(!DEBUG) { for(int i=0;i<n;i++) { ll x; cin>>x; people.pb(x); } for(int i=0;i<m;i++) { ll x; cin>>x; apple.pb(x); } } //build the graph cycles.clear(); for(int i=0;i<n;i++) { adj[i].clear();T[i].clear();w[i]=0;to[i]=0;visited[i]=0;iscyc[i]=0; shift[i]=0; subsize[i]=0; apples[i].clear(); queries[i].clear(); A[i]=NULL; } for(int i=0;i<n;i++) { ll curx = people[i]; curx-=C; curx%=L; if(curx<0) curx+=L; //first person that is <= curx gets it int ub = upper_bound(people.begin(),people.end(),curx)-people.begin(); ub--; if(ub<0) { ub=int(people.size())-1; } //ub is the person you want //compute the length now ll dist = 0; if(ub<=i) dist = people[i]-people[ub]; else dist = L-(people[ub]-people[i]); //we want dist >= C if(dist<C) { ll diff = C-dist; dist+=((diff+L-1)/L)*L; //ceil(diff/L)*L } w[i]=dist; to[i]=ub; adj[i].pb(to[i]); adj[to[i]].pb(i); //cerr<<i<<' '<<to[i]<<' '<<w[i]<<'\n'; } for(int i=0;i<m;i++) { ll pos = apple[i]; int ub = upper_bound(people.begin(),people.end(),pos)-people.begin(); ub--; if(ub<0) { ub=int(people.size())-1; } ll dist = D(people[ub],apple[i]); apples[ub].pb(dist); } //get the cycles for(int i=0;i<n;i++) { if(!visited[i]) { path.clear(); getcycles(i); } } //all cycles are stored now //get the trees vector<ii> QQ; int q; if(!DEBUG) cin>>q; else { if(n==0) q=0; else q = rand()%50+1; } for(int i=0;i<q;i++) ans[i]=ans2[i]=0; for(int z=0;z<q;z++) { int p; ll t; if(!DEBUG) { cin>>p>>t; p--; } else { p=rand()%n; t=rand()%50+1; } if(DEBUG) { vi curpos=people; vi nxtapple(L,ll(1e18)+10); for(int i=0;i<m;i++) { nxtapple[apple[i]]=0; } ll ans=0; for(ll i=0;i<t;i++) { for(int i=0;i<n;i++) { curpos[i]++; if(curpos[i]>=L) curpos[i]-=L; } for(int j=0;j<n;j++) { if(nxtapple[curpos[j]]<=i) { if(j==p) ans++; nxtapple[curpos[j]]=i+C; } } } ans2[z]=ans; QQ.pb({p,t}); } queries[p].pb({t,z}); } for(int i=0;i<n;i++) { if(iscyc[i]) { dfs(i); } } for(int i=0;i<n;i++) { for(ll &v:T[i]) { if(subsize[v]>subsize[T[i][0]]) { swap(v,T[i][0]); } } } //let's check if it works first //naively push everything from the trees? //later optimize to dsu on tree for(int i=0;i<n;i++) { if(iscyc[i]) { getA(i); } } //stuff on tree, use dsu on tree /* for(int i=0;i<n;i++) { cerr<<i<<' '<<shift[i]<<'\n'; for(ii x:(*A[i])) cerr<<x.fi<<'\n'; } */ //stuff on cycle, store 2 sets bruh for(int i=0;i<cycles.size();i++) { vi cyc = cycles[i]; ll cyclen = 0; for(int nd:cyc) cyclen+=w[nd]; vector<pair<ll,ll> > mods; vector<ll> coords; { ll curw = 0; for(int j=0;j<cyc.size();j++) { for(ii x:(*A[cyc[j]])) { coords.pb(x.fi+shift[cyc[j]]-curw); mods.pb({md(x.fi+shift[cyc[j]]-curw,cyclen),x.se}); } curw+=w[cyc[j]]; } } { ll curw = cyclen; for(int j=int(cyc.size())-1;j>0;j--) { curw-=w[cyc[j]]; for(ii x:(*A[cyc[j]])) mods.pb({md(x.fi+shift[cyc[j]]-curw+cyclen,cyclen),x.se}); } } sort(mods.begin(),mods.end()); mods.erase(unique(mods.begin(),mods.end()),mods.end()); sort(coords.begin(),coords.end()); coords.erase(unique(coords.begin(),coords.end()),coords.end()); Fenwick fen(coords.size()+10); Fenwick fen2(coords.size()+10); { vector<ll> V; ll curw = 0; for(int j=0;j<cyc.size();j++) { for(ii x:(*A[cyc[j]])) { int id = lower_bound(coords.begin(),coords.end(),x.fi+shift[cyc[j]]-curw)-coords.begin(); fen.update(id+1,flr(x.fi+shift[cyc[j]]-curw,cyclen)); fen2.update(id+1,1); //cerr<<"INSERT "<<x.fi-curw<<' '<<id<<' '<<flr(x.fi-curw,cyclen)<<' '<<md(x.fi-curw,cyclen)<<'\n'; int lb = lower_bound(mods.begin(),mods.end(),mp(md(x.fi+shift[cyc[j]]-curw,cyclen),x.se))-mods.begin(); update(1,0,int(coords.size()),id,lb); } //V.pb(x.fi-curw); for(ii qry:queries[cyc[j]]) { int lab = qry.se; ll T = qry.fi; T-=curw; int id = upper_bound(coords.begin(),coords.end(),T)-coords.begin(); id--; if(id>=0) { int ub = upper_bound(mods.begin(),mods.end(),mp(md(T,cyclen)+1,-1LL))-mods.begin(); ans[lab]+=(flr(T,cyclen)+1)*1LL*fen2.query(id+1) - fen.query(id+1) - query(1,0,int(coords.size()),0,id+1,ub); } } curw+=w[cyc[j]]; } //fen = Fenwick(coords.size()+10); //fen2 = Fenwick(coords.size()+10); } for(int nd:affected){mx[nd]=0; st[nd].clear();} affected.clear(); coords.clear(); { ll curw = cyclen; for(int j=int(cyc.size())-1;j>0;j--) { curw-=w[cyc[j]]; for(ii x:(*A[cyc[j]])) coords.pb(x.fi+shift[cyc[j]]-curw+cyclen); } } sort(coords.begin(),coords.end()); coords.erase(unique(coords.begin(),coords.end()),coords.end()); fen = Fenwick(coords.size()+10); fen2 = Fenwick(coords.size()+10); { vector<ll> V; ll curw = cyclen; for(int j=int(cyc.size())-1;j>0;j--) { curw-=w[cyc[j]]; for(ii x:(*A[cyc[j]])) { int id = lower_bound(coords.begin(),coords.end(),x.fi+shift[cyc[j]]-curw+cyclen)-coords.begin(); fen.update(id+1,flr(x.fi+shift[cyc[j]]-curw+cyclen,cyclen)); fen2.update(id+1,1); int lb = lower_bound(mods.begin(),mods.end(),mp(md(x.fi+shift[cyc[j]]-curw+cyclen,cyclen),x.se))-mods.begin(); //cerr<<"INSERT "<<x.fi-curw+cyclen<<' '<<id<<' '<<flr(x.fi-curw+cyclen,cyclen)<<' '<<md(x.fi-curw+cyclen,cyclen)<<'\n'; update(1,0,int(coords.size()),id,lb); } for(ii qry:queries[cyc[j-1]]) { int lab = qry.se; ll T = qry.fi; T-=curw-w[cyc[j-1]]; int id = upper_bound(coords.begin(),coords.end(),T)-coords.begin(); id--; if(id>=0) { //cerr<<lab<<' '<<"T: "<<T<<' '<<(flr(T,cyclen)+1)*1LL*fen2.query(id+1) - fen.query(id+1) - query(1,0,int(coords.size()),0,id+1,md(T,cyclen))<<'\n'; //cerr<<query(1,0,int(coords.size()),0,id+1,md(T,cyclen))<<' '<<fen2.query(id+1)<<' '<<fen.query(id+1)<<'\n'; int ub = upper_bound(mods.begin(),mods.end(),mp(md(T,cyclen)+1,-1LL))-mods.begin(); ans[lab]+=(flr(T,cyclen)+1)*1LL*fen2.query(id+1) - fen.query(id+1) - query(1,0,int(coords.size()),0,id+1,ub); } /* for(ll x:V) { if(T>=x) ans[lab]+=flr(T,cyclen) - flr(x,cyclen) - (md(T,cyclen)<md(x,cyclen)) + 1; } */ } } } for(int nd:affected) {mx[nd]=0;st[nd].clear();} affected.clear(); } if(!DEBUG) { for(int z=0;z<q;z++) { cout<<ans[z]<<'\n'; } return 0; } for(int z=0;z<q;z++) { if(ans2[z]!=ans[z]) { cerr<<"FAIL AT "<<z<<" ans = "<<ans[z]<<" ans2 = "<<ans2[z]<<'\n'; freopen("harvest-fail.out","w",stdout); cout<<n<<' '<<m<<' '<<L<<' '<<C<<'\n'; for(int i=0;i<n;i++) cout<<people[i]<<' '; cout<<'\n'; for(int i=0;i<m;i++) cout<<apple[i]<<' '; cout<<'\n'; cout<<q<<'\n'; for(ii x:QQ) cout<<x.fi+1<<' '<<x.se<<'\n'; return 0; } } cerr<<"Case #"<<cc<<" complete\n"; } }

Compilation message (stderr)

harvest.cpp:5:0: warning: ignoring #pragma GCC optimization [-Wunknown-pragmas]
 #pragma GCC optimization ("O3")
 
harvest.cpp:6:0: warning: ignoring #pragma GCC optimization [-Wunknown-pragmas]
 #pragma GCC optimization ("unroll-loops")
 
harvest.cpp: In function 'int main()':
harvest.cpp:384:16: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
   for(int i=0;i<cycles.size();i++)
               ~^~~~~~~~~~~~~~
harvest.cpp:393:18: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
     for(int j=0;j<cyc.size();j++)
                 ~^~~~~~~~~~~
harvest.cpp:420:18: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
     for(int j=0;j<cyc.size();j++)
                 ~^~~~~~~~~~~
harvest.cpp:520:12: warning: ignoring return value of 'FILE* freopen(const char*, const char*, FILE*)', declared with attribute warn_unused_result [-Wunused-result]
     freopen("harvest-fail.out","w",stdout);
     ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...