Submission #727417

#TimeUsernameProblemLanguageResultExecution timeMemory
727417model_codeChorus (JOI23_chorus)C++17
100 / 100
3505 ms140680 KiB
#ifndef LOCAL #pragma GCC optimize ("Ofast") #pragma GCC optimize ("unroll-loops") #endif #include <bits/stdc++.h> using namespace std; using ll=long long; #define int ll #define rng(i,a,b) for(int i=int(a);i<int(b);i++) #define rep(i,b) rng(i,0,b) #define gnr(i,a,b) for(int i=int(b)-1;i>=int(a);i--) #define per(i,b) gnr(i,0,b) #define pb push_back #define eb emplace_back #define a first #define b second #define bg begin() #define ed end() #define all(x) x.bg,x.ed #define si(x) int(x.size()) #ifdef LOCAL #define dmp(x) cerr<<__LINE__<<" "<<#x<<" "<<x<<endl #else #define dmp(x) void(0) #endif template<class t,class u> bool chmax(t&a,u b){if(a<b){a=b;return true;}else return false;} template<class t,class u> bool chmin(t&a,u b){if(b<a){a=b;return true;}else return false;} template<class t> using vc=vector<t>; template<class t> using vvc=vc<vc<t>>; using pi=pair<int,int>; using vi=vc<int>; template<class t,class u> ostream& operator<<(ostream& os,const pair<t,u>& p){ return os<<"{"<<p.a<<","<<p.b<<"}"; } template<class t> ostream& operator<<(ostream& os,const vc<t>& v){ os<<"{"; for(auto e:v)os<<e<<","; return os<<"}"; } #define mp make_pair #define mt make_tuple #define one(x) memset(x,-1,sizeof(x)) #define zero(x) memset(x,0,sizeof(x)) #ifdef LOCAL void dmpr(ostream&os){os<<endl;} template<class T,class... Args> void dmpr(ostream&os,const T&t,const Args&... args){ os<<t<<" "; dmpr(os,args...); } #define dmp2(...) dmpr(cerr,__LINE__,##__VA_ARGS__) #else #define dmp2(...) void(0) #endif using uint=unsigned; using ull=unsigned long long; template<class t,size_t n> ostream& operator<<(ostream&os,const array<t,n>&a){ return os<<vc<t>(all(a)); } template<int i,class T> void print_tuple(ostream&,const T&){ } template<int i,class T,class H,class ...Args> void print_tuple(ostream&os,const T&t){ if(i)os<<","; os<<get<i>(t); print_tuple<i+1,T,Args...>(os,t); } template<class ...Args> ostream& operator<<(ostream&os,const tuple<Args...>&t){ os<<"{"; print_tuple<0,tuple<Args...>,Args...>(os,t); return os<<"}"; } template<class t> void print(t x,int suc=1){ cout<<x; if(suc==1) cout<<"\n"; if(suc==2) cout<<" "; } ll read(){ ll i; cin>>i; return i; } vi readvi(int n,int off=0){ vi v(n); rep(i,n)v[i]=read()+off; return v; } pi readpi(int off=0){ int a,b;cin>>a>>b; return pi(a+off,b+off); } template<class t,class u> void print(const pair<t,u>&p,int suc=1){ print(p.a,2); print(p.b,suc); } template<class t,class u> void print_offset(const pair<t,u>&p,ll off,int suc=1){ print(p.a+off,2); print(p.b+off,suc); } template<class T> void print(const vector<T>&v,int suc=1){ rep(i,v.size()) print(v[i],i==int(v.size())-1?suc:2); } template<class T> void print_offset(const vector<T>&v,ll off,int suc=1){ rep(i,v.size()) print(v[i]+off,i==int(v.size())-1?suc:2); } template<class T,size_t N> void print(const array<T,N>&v,int suc=1){ rep(i,N) print(v[i],i==int(N)-1?suc:2); } string readString(){ string s; cin>>s; return s; } template<class T> T sq(const T& t){ return t*t; } void YES(bool ex=true){ cout<<"YES\n"; if(ex)exit(0); #ifdef LOCAL cout.flush(); #endif } void NO(bool ex=true){ cout<<"NO\n"; if(ex)exit(0); #ifdef LOCAL cout.flush(); #endif } void Yes(bool ex=true){ cout<<"Yes\n"; if(ex)exit(0); #ifdef LOCAL cout.flush(); #endif } void No(bool ex=true){ cout<<"No\n"; if(ex)exit(0); #ifdef LOCAL cout.flush(); #endif } //#define CAPITAL /* void yes(bool ex=true){ #ifdef CAPITAL cout<<"YES"<<"\n"; #else cout<<"Yes"<<"\n"; #endif if(ex)exit(0); #ifdef LOCAL cout.flush(); #endif } void no(bool ex=true){ #ifdef CAPITAL cout<<"NO"<<"\n"; #else cout<<"No"<<"\n"; #endif if(ex)exit(0); #ifdef LOCAL cout.flush(); #endif }*/ void possible(bool ex=true){ #ifdef CAPITAL cout<<"POSSIBLE"<<"\n"; #else cout<<"Possible"<<"\n"; #endif if(ex)exit(0); #ifdef LOCAL cout.flush(); #endif } void impossible(bool ex=true){ #ifdef CAPITAL cout<<"IMPOSSIBLE"<<"\n"; #else cout<<"Impossible"<<"\n"; #endif if(ex)exit(0); #ifdef LOCAL cout.flush(); #endif } constexpr ll ten(int n){ return n==0?1:ten(n-1)*10; } const ll infLL=LLONG_MAX/3; #ifdef int const int inf=infLL; #else const int inf=INT_MAX/2-100; #endif int topbit(signed t){ return t==0?-1:31-__builtin_clz(t); } int topbit(ll t){ return t==0?-1:63-__builtin_clzll(t); } int topbit(ull t){ return t==0?-1:63-__builtin_clzll(t); } int botbit(signed a){ return a==0?32:__builtin_ctz(a); } int botbit(ll a){ return a==0?64:__builtin_ctzll(a); } int botbit(ull a){ return a==0?64:__builtin_ctzll(a); } int popcount(signed t){ return __builtin_popcount(t); } int popcount(ll t){ return __builtin_popcountll(t); } int popcount(ull t){ return __builtin_popcountll(t); } bool ispow2(int i){ return i&&(i&-i)==i; } ll mask(int i){ return (ll(1)<<i)-1; } ull umask(int i){ return (ull(1)<<i)-1; } ll minp2(ll n){ if(n<=1)return 1; else return ll(1)<<(topbit(n-1)+1); } bool inc(int a,int b,int c){ return a<=b&&b<=c; } template<class t> void mkuni(vc<t>&v){ sort(all(v)); v.erase(unique(all(v)),v.ed); } ll rand_int(ll l, ll r) { //[l, r] //#ifdef LOCAL static mt19937_64 gen; /*#else static mt19937_64 gen(chrono::steady_clock::now().time_since_epoch().count()); #endif*/ return uniform_int_distribution<ll>(l, r)(gen); } ll rand_int(ll k){ //[0,k) return rand_int(0,k-1); } template<class t> void myshuffle(vc<t>&a){ rep(i,si(a))swap(a[i],a[rand_int(0,i)]); } template<class t> int lwb(const vc<t>&v,const t&a){ return lower_bound(all(v),a)-v.bg; } template<class t> bool bis(const vc<t>&v,const t&a){ return binary_search(all(v),a); } vvc<int> readGraph(int n,int m){ vvc<int> g(n); rep(i,m){ int a,b; cin>>a>>b; //sc.read(a,b); a--;b--; g[a].pb(b); g[b].pb(a); } return g; } vvc<int> readTree(int n){ return readGraph(n,n-1); } vc<ll> presum(const vi&a){ vc<ll> s(si(a)+1); rep(i,si(a))s[i+1]=s[i]+a[i]; return s; } //BIT で数列を管理するときに使う (CF850C) template<class t> vc<t> predif(vc<t> a){ gnr(i,1,si(a))a[i]-=a[i-1]; return a; } template<class t> void transvvc(int&n,int&m,vvc<t>&a){ assert(si(a)==n); vvc<int> b(m,vi(n)); rep(i,n){ assert(si(a[i])==m); rep(j,m)b[j][i]=a[i][j]; } a.swap(b); swap(n,m); } //ソートして i 番目が idx[i] //CF850C template<class t> vi sortidx(const vc<t>&a){ int n=si(a); vi idx(n);iota(all(idx),0); sort(all(idx),[&](int i,int j){return a[i]<a[j];}); return idx; } //vs[i]=a[idx[i]] //例えば sortidx で得た idx を使えば単にソート列になって返ってくる //CF850C template<class t> vc<t> a_idx(const vc<t>&a,const vi&idx){ int n=si(a); assert(si(idx)==n); vc<t> vs(n); rep(i,n)vs[i]=a[idx[i]]; return vs; } //CF850C vi invperm(const vi&p){ int n=si(p); vi q(n); rep(i,n)q[p[i]]=i; return q; } template<class t,class s=t> s SUM(const vc<t>&a){ return accumulate(all(a),s(0)); } //ä½¿ã£ãŸã‚¹ãƒ†ãƒƒãƒ—æ•°ã®æƒ…å ±ã‚’æŒã¤ convex hull //F(a,b)=true なら a を優先 //min-hull なら less をいれればいい //eval の値が 10^18 オーダーならだいたいうまく行くようになっているはず //stress-tested (CC 2023-2 Cookoff G) struct linelr{ int a,b,c,d; int eval(int x){ return a*x+b; } }; ostream&operator<<(ostream&os,const linelr&ln){ return os<<"L{"<<ln.a<<","<<ln.b<<","<<ln.c<<","<<ln.d<<"}"; } template<class F> struct vlr{ int v=F()(inf,-inf)?-inf:inf,l=-inf,r=inf; static vlr merge(const vlr&a,const vlr&b){ if(F()(a.v,b.v))return a; else if(F()(b.v,a.v))return b; else return {a.v,min(a.l,b.l),max(a.r,b.r)}; } bool operator==(const vlr&rhs)const{ return v==rhs.v&&l==rhs.l&&r==rhs.r; } bool operator!=(const vlr&rhs)const{ return v!=rhs.v||l!=rhs.l||r!=rhs.r; } vlr operator+(int a)const{ return {v+a,l,r}; } void adv(int a){ v+=a; l++; r++; } }; template<class F> ostream&operator<<(ostream&os,const vlr<F>&z){ return os<<"vlr{"<<z.v<<",["<<z.l<<","<<z.r<<"]}"; } template<class F> struct chtlr{ static int fdiv(int a,int b){ return a / b - ((a ^ b) < 0 && a % b); } static int cdiv(int a,int b){ return a / b + ((a ^ b) > 0 && a % b); } //can b be the opt? static bool cmpline(const linelr&a,const linelr&b,const linelr&c){ int ay=a.b-b.b,ax=b.a-a.a; int by=b.b-c.b,bx=c.a-b.a; return cdiv(ay,ax)<=fdiv(by,bx); } vector<linelr> ls; int head,prex; vlr<F> preres; chtlr(){clear();} void clear(){ ls.clear(); head=0; prex=-inf; preres=vlr<F>(); } //min-hull -> z.a is non-increasing void add(linelr z){ if(si(ls))assert(!F()(ls.back().a,z.a)); if(prex!=-inf)preres=vlr<F>::merge(preres,{z.eval(prex),z.c,z.d}); if(si(ls)&&ls.back().a==z.a){ auto&w=ls.back(); if(F()(w.b,z.b)){ return; }else if(F()(z.b,w.b)){ ls.pop_back(); }else{ chmin(w.c,z.c); chmax(w.d,z.d); return; } } while(si(ls)>=2){ int s=si(ls); if(cmpline(ls[s-2],ls[s-1],z)) break; ls.pop_back(); } chmin(head,si(ls)); ls.push_back(z); } void add(int a,int b,int c,int d){add(linelr{a,b,c,d});} //x is non-decreasing vlr<F> query(int x){ if(ls.empty())return vlr<F>(); assert(prex<=x); if(prex==x)return preres; while(head+1<si(ls)){ if(F()(ls[head+1].eval(x),ls[head].eval(x))) head++; else break; } int res=ls[head].eval(x),c=ls[head].c,d=ls[head].d; while(head+1<si(ls)&&!F()(res,ls[head+1].eval(x))){ head++; chmin(c,ls[head].c); chmax(d,ls[head].d); } prex=x; return preres={res,c,d}; } }; //monge コストでちょうど k step でやれ,みたいな最小化問題 //max(f(x))-max(f(x)) の上界を dif で与えている template<class F> int kstepmin(int k,int dif,F f){ assert(dif>=0); int lw=-1; int up=dif+1; while(up-lw>1){ int mid=(lw+up)/2; auto z=f(mid); if(z.r<k){ up=mid; }else if(k<z.l){ lw=mid; }else return z.v-mid*k; } dmp2(lw,up); assert(false); } //stress-tested template<class N> struct slide_monoid{ vc<N> a,b; int head,mid; slide_monoid(){clear();} void clear(){ a.clear(); b.clear();b.eb(); head=0; mid=0; } void push(const N&x){ a.pb(x); b.pb(N::merge(b.back(),x)); } void pop(){ if(++head>mid){ b.back()=N(); mid=si(b)-1; gnr(i,head,mid) b[i]=N::merge(a[i],b[i+1]); } assert(head<=mid); } N get(){ return N::merge(b[head],b.back()); } }; int slv(int n,int k,string s){ int off=0; vi a; { int x=0,y=0; rep(i,2*n){ if(s[i]=='A'){ int v=min(x,y); off+=y-v; a.pb(v); x++; }else{ y++; } } } vi b=presum(a); using V=vlr<less<int>>; chtlr<less<int>> cht; slide_monoid<V> sm; vc<V> dp(n+1); auto f=[&](int cost)->V{ cht.clear(); sm.clear(); int j=0; rep(i,n+1){ if(i==0){ dp[i]={0,0,0}; }else{ dp[i]=V::merge(cht.query(i)+b[i],sm.get()); dp[i].adv(cost); } sm.push(dp[i]); if(i<n){ while(j<a[i]){ sm.pop(); cht.add(-j,dp[j].v-b[i]+j*i,dp[j].l,dp[j].r); j++; } } } return dp[n]; }; return kstepmin(k,n*n,f)+off; } signed main(){ cin.tie(0); ios::sync_with_stdio(0); cout<<fixed<<setprecision(20); int n,k;cin>>n>>k; string s;cin>>s; print(slv(n,k,s)); }
#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...