제출 #743229

#제출 시각아이디문제언어결과실행 시간메모리
743229emptypringlescanTwo Currencies (JOI23_currencies)C++17
0 / 100
5064 ms159928 KiB
#include <bits/stdc++.h> using namespace std; struct node{ int s,e,m; long long val; int cnt; node *l,*r; node(int S, int E){ s=S; e=E; m=(s+e)/2; l=r=NULL; val=cnt=0; } void prop(){ if(l==NULL){ l=new node(s,m); r=new node(m+1,e); } } void update(int S, int N){ if(s==e){ val+=(long long)s*N; cnt+=N; return; } prop(); if(S<=m) l->update(S,N); else r->update(S,N); val=l->val+r->val; cnt=l->cnt+r->cnt; } int query(long long V){ if(s==e){ return V/(long long)s; } prop(); if(l->val>V) return l->query(V); else return l->cnt+r->query(V-l->val); } } *root; vector<int> adj[200005],eul; int fi[200005],se[200005]; long long cost[200005]; void dfs(int x, int p){ fi[x]=eul.size(); eul.push_back(x); for(int i:adj[x]){ if(i!=p) dfs(i,x); } se[x]=eul.size(); eul.push_back(x); } const int MAXN = 200050; const int LOGN = 20; int p[LOGN+1][MAXN], h[MAXN]; //h: number of edges from root bitset<MAXN> visited; void dfss(int x) { if (visited[x]) return; visited[x] = 1; for (int k = 0; k < LOGN; ++k) { if (p[k][x] == -1) break; p[k+1][x] = p[k][p[k][x]]; } for (int it:adj[x]) { if (visited[it]) continue; p[0][it] = x; h[it] = h[x] + 1; dfss(it); } } /* Query */ int lca(int a, int b) { //h[a] < h[b] if (h[a] > h[b]) swap(a, b); /* advance b by h[b] - h[a] parents */ for (int k = 0, d = h[b] - h[a]; k < LOGN; ++k) { if (d & (1<<k)) b = p[k][b]; } if (a == b) return a; assert(h[a] == h[b]); //same height /* to be continued */ for (int k = LOGN-1; k >= 0; --k) { if (p[k][a] != p[k][b]) a = p[k][a], b = p[k][b]; } assert(p[0][a] == p[0][b]); //same immediate parent return p[0][a]; } bool cmp(pair<pair<int,int>,pair<pair<int,pair<int,long long> >,int> > a,pair<pair<int,int>,pair<pair<int,pair<int,long long> >,int> > b){ if(a.first.first==b.first.first){ if((a.first.first&1)==0) return a.first.second<b.first.second; else return a.first.second>b.first.second; } return a.first.first<b.first.first; } int32_t main(){ ios::sync_with_stdio(0); cin.tie(0); memset(p,-1,sizeof(p)); int n,m,q; cin >> n >> m >> q; vector<pair<int,int> > edges; for(int i=0; i<n-1; i++){ int a,b; cin >> a >> b; edges.push_back({a,b}); } int cnt=n+1; for(int i=0; i<m; i++){ int a; long long b; cin >> a >> b; cost[cnt]=b; edges.push_back({cnt,edges[a-1].second}); edges[a-1].second=cnt; cnt++; } for(auto i:edges){ adj[i.first].push_back(i.second); adj[i.second].push_back(i.first); } dfs(1,-1); dfss(1); int buc=450; long long ans[q]; pair<pair<int,int>,pair<pair<int,pair<int,long long> >,int> > qu[q]; pair<int,int> org[q]; for(int i=0; i<q; i++){ int a,b; long long c,d; cin >> a >> b >> c >> d; org[i]={a,b}; int x=0,y=0,o=-1; if(se[a]<fi[b]){ x=se[a]; y=fi[b]; o=lca(a,b); } else if(se[b]<fi[a]){ x=se[b]; y=fi[a]; o=lca(a,b); } else if(fi[a]<fi[b]){ x=fi[a]; y=fi[b]; } else{ x=fi[b]; y=fi[a]; } ans[i]=c; qu[i]={{x/buc,y},{{o,{i,d}},x}}; } sort(qu,qu+q,cmp); int c1=0,c2=0,nds=0; root=new node(0,1000000005); int got[cnt]; memset(got,0,sizeof(got)); for(int i=0; i<q; i++){ while(c2<=qu[i].first.second){ if(got[eul[c2]]==0){ got[eul[c2]]=1; nds++; root->update(cost[eul[c2]],1); } else{ got[eul[c2]]=0; nds--; root->update(cost[eul[c2]],-1); } c2++; } while(c1>qu[i].second.second){ c1--; if(got[eul[c1]]==0){ got[eul[c1]]=1; nds++; root->update(cost[eul[c1]],1); } else{ got[eul[c1]]=0; nds--; root->update(cost[eul[c1]],-1); } } while(c2>qu[i].first.second+1){ c2--; if(got[eul[c2]]==0){ got[eul[c2]]=1; nds++; root->update(cost[eul[c2]],1); } else{ got[eul[c2]]=0; nds--; root->update(cost[eul[c2]],-1); } } while(c1<qu[i].second.second){ if(got[eul[c1]]==0){ got[eul[c1]]=1; nds++; root->update(cost[eul[c1]],1); } else{ got[eul[c1]]=0; nds--; root->update(cost[eul[c1]],-1); } c1++; } if(qu[i].second.first.first!=-1){ int o=qu[i].second.first.first; if(got[o]==0){ got[o]=1; nds++; root->update(cost[o],1); } else{ got[o]=0; nds--; root->update(cost[o],-1); } } int heh=root->query(qu[i].second.first.second.second); ans[qu[i].second.first.second.first]-=(nds-heh); if(qu[i].second.first.first!=-1){ int o=qu[i].second.first.first; if(got[o]==0){ got[o]=1; nds++; root->update(cost[o],1); } else{ got[o]=0; nds--; root->update(cost[o],-1); } } } for(int i=0; i<q; i++){ if(ans[i]<0) cout << -1 << '\n'; else cout << ans[i] << '\n'; } }
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...