Submission #939651

#TimeUsernameProblemLanguageResultExecution timeMemory
939651andrei_boacaFish 2 (JOI22_fish2)C++17
100 / 100
1876 ms35608 KiB
#include <bits/stdc++.h> using namespace std; typedef long long ll; const ll INF=1e17; typedef pair<int,int> pii; ll n,v[100005],q,s[100005],mars[100005]; int solve(int l,int r) { s[l-1]=0; mars[l-1]=0; for(int i=l;i<=r;i++) { s[i]=s[i-1]+v[i]; mars[i]=0; } stack<int> coada; for(int i=l;i<=r;i++) { while(!coada.empty()&&v[coada.top()]<v[i]) coada.pop(); int st=l-1; if(!coada.empty()) st=coada.top(); if(s[i-1]-s[st]<v[i]) { mars[st+1]++; mars[i]--; } coada.push(i); } while(!coada.empty()) coada.pop(); for(int i=r;i>=l;i--) { while(!coada.empty()&&v[coada.top()]<v[i]) coada.pop(); int dr=r+1; if(!coada.empty()) dr=coada.top(); if(s[dr-1]-s[i]<v[i]) { mars[i+1]++; mars[dr]--; } coada.push(i); } int ans=0; for(int i=l;i<=r;i++) { mars[i]+=mars[i-1]; if(mars[i]==0) ans++; } return ans; } ll aib[100005]; ll lsb(ll x) { return x&(-x); } void aibupd(ll poz,ll val) { for(int i=poz;i<=n;i+=lsb(i)) aib[i]+=val; } ll suma(ll poz) { ll rez=0; for(int i=poz;i>=1;i-=lsb(i)) rez+=aib[i]; return rez; } struct date { ll minim,cnt; } arb[4*100005]; ll toprop[4*100005]; struct prostie { ll maxim,poz; } arbdir[2][4*100005]; /// 0 -> st, 1 -> dr ll topropdir[2][4*100005]; date combine(date a, date b) { if(a.minim<b.minim) return a; if(a.minim>b.minim) return b; a.cnt+=b.cnt; return a; } void prop(ll nod) { ll val=toprop[nod]; arb[nod*2].minim+=val; arb[nod*2+1].minim+=val; toprop[nod*2]+=val; toprop[nod*2+1]+=val; } void update(ll nod,ll st,ll dr,ll a,ll b,ll val) { if(st!=dr) prop(nod); toprop[nod]=0; if(st>=a&&dr<=b) { arb[nod].minim+=val; toprop[nod]+=val; return; } ll mij=(st+dr)/2; if(a<=mij) update(nod*2,st,mij,a,b,val); if(b>mij) update(nod*2+1,mij+1,dr,a,b,val); arb[nod]=combine(arb[nod*2],arb[nod*2+1]); } date query(ll nod,ll st,ll dr,ll a,ll b) { if(st!=dr) prop(nod); toprop[nod]=0; if(st>=a&&dr<=b) return arb[nod]; date rez={2LL*INF,0}; ll mij=(st+dr)/2; if(a<=mij) rez=combine(rez,query(nod*2,st,mij,a,b)); if(b>mij) rez=combine(rez,query(nod*2+1,mij+1,dr,a,b)); return rez; } prostie combinedir(prostie a, prostie b) { if(a.maxim>=b.maxim) return a; return b; } void propdir(ll ind,ll nod) { ll val=topropdir[ind][nod]; arbdir[ind][nod*2].maxim+=val; arbdir[ind][nod*2+1].maxim+=val; topropdir[ind][nod*2]+=val; topropdir[ind][nod*2+1]+=val; } void updatedir(ll ind,ll nod,ll st,ll dr,ll a,ll b,ll val) { if(st!=dr) propdir(ind,nod); topropdir[ind][nod]=0; if(st>=a&&dr<=b) { arbdir[ind][nod].maxim+=val; topropdir[ind][nod]+=val; return; } ll mij=(st+dr)/2; if(a<=mij) updatedir(ind,nod*2,st,mij,a,b,val); if(b>mij) updatedir(ind,nod*2+1,mij+1,dr,a,b,val); arbdir[ind][nod]=combinedir(arbdir[ind][nod*2],arbdir[ind][nod*2+1]); } prostie querydir(ll ind,ll nod,ll st,ll dr,ll a,ll b) { if(st!=dr) propdir(ind,nod); topropdir[ind][nod]=0; if(st>=a&&dr<=b) return arbdir[ind][nod]; prostie rez={-2LL*INF,0}; ll mij=(st+dr)/2; if(a<=mij) rez=combinedir(rez,querydir(ind,nod*2,st,mij,a,b)); if(b>mij) rez=combinedir(rez,querydir(ind,nod*2+1,mij+1,dr,a,b)); return rez; } void build(int nod,int st,int dr) { arb[nod].cnt=(dr-st+1); if(st==dr) return; int mij=(st+dr)/2; build(nod*2,st,mij); build(nod*2+1,mij+1,dr); } void builddir(int nod,int st,int dr) { arbdir[0][nod]=arbdir[1][nod]={0,st}; if(st==dr) return; int mij=(st+dr)/2; builddir(nod*2,st,mij); builddir(nod*2+1,mij+1,dr); } set<pii> setik; int main() { ios_base::sync_with_stdio(false); cin.tie(0); cin>>n; for(int i=1;i<=n;i++) cin>>v[i]; cin>>q; v[0]=INF; v[n+1]=INF; build(1,1,n); builddir(1,1,n); for(int i=1;i<=n;i++) aibupd(i,v[i]); stack<int> coada; for(int i=1;i<=n;i++) { while(!coada.empty()&&v[coada.top()]<v[i]) coada.pop(); int st=0; if(!coada.empty()) st=coada.top(); if(suma(i-1)-suma(st)<v[i]) { /*mars[st+1]++; mars[i]--;*/ if(st+1<=i-1) setik.insert({st+1,i-1}); } coada.push(i); } while(!coada.empty()) coada.pop(); for(int i=n;i>=1;i--) { while(!coada.empty()&&v[coada.top()]<v[i]) coada.pop(); int dr=n+1; if(!coada.empty()) dr=coada.top(); if(suma(dr-1)-suma(i)<v[i]) { /*mars[i+1]++; mars[dr]--;*/ if(i+1<=dr-1) setik.insert({i+1,dr-1}); } coada.push(i); } while(!coada.empty()) coada.pop(); for(int i=1;i<=n;i++) { updatedir(0,1,1,n,i,i,v[i]); updatedir(1,1,1,n,i,i,v[i]); if(i+1<=n) updatedir(0,1,1,n,i+1,n,-v[i]); if(i-1>=1) updatedir(1,1,1,n,1,i-1,-v[i]); } for(auto p:setik) update(1,1,n,p.first,p.second,+1); while(q--) { ll tip; cin>>tip; if(tip==1) { ll i,val; cin>>i>>val; updatedir(0,1,1,n,i,i,-v[i]); updatedir(1,1,1,n,i,i,-v[i]); if(i+1<=n) updatedir(0,1,1,n,i+1,n,v[i]); if(i-1>=1) updatedir(1,1,1,n,1,i-1,v[i]); aibupd(i,-v[i]); v[i]=val; updatedir(0,1,1,n,i,i,v[i]); updatedir(1,1,1,n,i,i,v[i]); if(i+1<=n) updatedir(0,1,1,n,i+1,n,-v[i]); if(i-1>=1) updatedir(1,1,1,n,1,i-1,-v[i]); aibupd(i,v[i]); vector<int> lft,rgt; if(i>1) { ll S=suma(n)-suma(i-1); while(true) { prostie a=querydir(1,1,1,n,1,i-1); a.maxim+=S; if(a.maxim<0) break; lft.push_back(a.poz); updatedir(1,1,1,n,a.poz,a.poz,-INF); } for(ll p:lft) updatedir(1,1,1,n,p,p,+INF); } if(i+1<=n) { ll S=suma(i); while(true) { prostie a=querydir(0,1,1,n,i+1,n); a.maxim+=S; if(a.maxim<0) break; rgt.push_back(a.poz); updatedir(0,1,1,n,a.poz,a.poz,-INF); } for(ll p:rgt) updatedir(0,1,1,n,p,p,+INF); } lft.push_back(i); rgt.push_back(i); lft.push_back(0); rgt.push_back(n+1); for(ll l:lft) for(ll r:rgt) { ll st=l+1; ll dr=r-1; if(st<=dr) { if(suma(dr)-suma(st-1)<min(v[l],v[r])) { if(setik.find({st,dr})==setik.end()) { setik.insert({st,dr}); update(1,1,n,st,dr,+1); } } else { if(setik.find({st,dr})!=setik.end()) { setik.erase({st,dr}); update(1,1,n,st,dr,-1); } } } } } else { int l,r; cin>>l>>r; ll rgt=l; ll st=l; ll dr=r; ll S=suma(l-1); while(st<=dr) { ll mij=(st+dr)/2; prostie a=querydir(0,1,1,n,mij,r); if(a.maxim+S>0) { rgt=mij; st=mij+1; } else dr=mij-1; } rgt--; ll lft=r; S=suma(n)-suma(r); st=l; dr=r; while(st<=dr) { ll mij=(st+dr)/2; prostie a=querydir(1,1,1,n,l,mij); if(a.maxim+S>0) { lft=mij; dr=mij-1; } else st=mij+1; } lft++; if(l<=rgt) update(1,1,n,l,rgt,+1); if(lft<=r) update(1,1,n,lft,r,+1); date rez=query(1,1,n,l,r); if(l<=rgt) update(1,1,n,l,rgt,-1); if(lft<=r) update(1,1,n,lft,r,-1); cout<<rez.cnt<<'\n'; } } return 0; }
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...