제출 #835196

#제출 시각아이디문제언어결과실행 시간메모리
835196AntekbChorus (JOI23_chorus)C++17
100 / 100
5033 ms69608 KiB
#include<bits/stdc++.h>
#define st first
#define nd second
#define all(x) (x).begin(), (x).end()
#define pb push_back
#define eb emplace_back
#define pp pop_back
#define mp make_pair
using namespace std;
using pii = pair<int, int>;
using ll = long long;
using vi = vector<int>;
using vii = vector<pii>;
using ld = long double;
void debug(){cerr<<"\n";}
template<typename H, typename... T>
void debug(H h, T... t){
	cerr<<h;
	if(sizeof...(t)){
		cerr<<", ";
	}
	debug(t...);
}
#define deb(x...) cerr<<#x<<" = ";debug(x);

mt19937 rng(chrono::high_resolution_clock::now().time_since_epoch().count());
const int N=1<<20;
ld dp[N], ile[N];
int main(){
	int n, k;
	string s;
	cin>>n>>k>>s;
	ll res=0;
	vi V(n+1), pocz(n+1);
	vector<ll> sum={0};
	int a=0, b=1;
	for(char c:s){
		if(c=='A'){
			a++;
			pocz[a]=min(b, a)-1;
		}
		else{
			res+=max(0, b-a);
			V[b]=max(a, b);
			sum.pb(V[b]+sum.back());
			b++;
		}
	}
	deb(res);
	for(int i=1; i<=n; i++){
		//deb(i, V[i], pocz[i], sum[i]);
	}
	/*vector<vector<ll> > dp2(n+1, vector<ll>(k+1, 1e18));
	dp2[0][0]=0;
	for(int kk=1; kk<=k; kk++){
		for(int i=kk; i<=n; i++){
			ll c=0;
			for(int j=i-1; j>=0; j--){
				c+=max(0, i-V[j+1]);
				dp2[i][kk]=min(dp2[i][kk], dp2[j][kk-1]+c);
			}
		}
	}
	for(int kk=1; kk<=k; kk++){
		cout<<dp2[n][kk]<<" ";
	}*/
	ld l=-2e12, r=2e12;
	pair<int, ll> L,R;
	for(int ii=0; ii<70; ii++){
		ld m=(l+r)/2;
		dp[0]=0;
		ile[0]=0;
		deque<pair<ld, int> > V2;
		deque<int> tim;
		V2.eb(dp[0], 0);
		deb(m);
		for(int i=1; i<=n; i++){
			for(int j=pocz[i-1]+1; j<=pocz[i]; j++){
				ld A=dp[j]+sum[j];
				int B=-j;
				//deb(A, B);
				while(V2.size() && A<=V2.back().st){
					V2.pp();
					if(tim.size())tim.pp();
				}
				if(V2.empty()){
					V2.eb(A, B);
					continue;
				}
				ll t=ceil((A-V2.back().st)/(V2.back().nd-B))+1e-9;
				//deb(t);
				while(V2.size()>=2){
					if(t<=tim.back()){
						V2.pp();
						tim.pp();
						t=ceil((A-V2.back().st)/(V2.back().nd-B))+1e-9;
					}
					else break;
				}
				//if(t<=n){
				V2.eb(A,B);
				tim.pb(min(t, ll(n+1)));
				//}
			}
			while(tim.size() && tim.front()<=i){
				tim.pop_front();
				V2.pop_front();
			}
			dp[i]=V2.front().st+i*1ll*V2.front().nd+pocz[i]*1ll*i-sum[pocz[i]];
			ile[i]=ile[-V2.front().nd]+1;
			if(dp[i]>dp[i-1]){
				dp[i]=dp[i-1];
				ile[i]=ile[i-1]+1;
			}
			if(dp[i]>dp[pocz[i]]){
				dp[i]=dp[pocz[i]];
				ile[i]=ile[pocz[i]]+1;
			}
			dp[i]+=m;
			//deb(i, dp[i]);
		}
		/*int opt=0;
		//deb(m);
		for(int i=1; i<=n; i++){
			ll c=0;
			//dp[i]=1e18;
			//deb(i);
			if(i>1 && opt==0)opt++;
			ll c2=0;
			if(pocz[i]>opt)c2=(pocz[i]-opt)*1ll*i-sum[pocz[i]]+sum[opt];
			//dp[opt]+sum[opt]-opt*i dla opt<=pocz[i]
			//czyli jesli opt<opt2 i f(opt)>f(opt2) to zawsze pozniej bedzie
			//wiec i bedzie lepsze od i-1 od pewnego momentu
			//mozemy wrzucic wszystko na vector
			/*while(opt<i-1){
				ll c3=0;
				if(pocz[i]>opt+1)c3=(pocz[i]-opt-1)*1ll*i-sum[pocz[i]]+sum[opt+1];
				if(dp[opt]+c2>=dp[opt+1]+c3){
					opt++;
					c2=c3;
				}
				else break;
			}*/
			/*
			//if(dp[i]>dp[opt]+c2+m){
				dp[i]=dp[opt]+c2+m;
				ile[i]=ile[opt]+1;
			//}
			c2=0;
			if(pocz[i]>0)c2=pocz[i]*1ll*i-sum[pocz[i]];
			if(dp[i]>dp[0]+c2+m){
				dp[i]=dp[0]+c2+m;
				ile[i]=ile[0]+1;
			}
			deb(i, opt, dp[i], pocz[i]);
			for(int j=i-1; j>=0; j--){
				c+=max(0, i-V[j+1]);
				c2=0;
				if(pocz[i]>j)c2=(pocz[i]-j)*1ll*i-sum[pocz[i]]+sum[j];
				deb(i, j, dp[i], dp[j]+c+m);
				assert(c==c2);
				//deb(j, dp[j], dp[j]+c+m);
			}
			c=0;
			ld x=1e18;
			for(int j=i-1; j>=0; j--){
				c+=max(0, i-V[j+1]);
				c2=0;
				if(pocz[i]>j)c2=(pocz[i]-j)*1ll*i-sum[pocz[i]]+sum[j];
				//deb(i, j, dp[i], dp[j]+c+m);
				assert(c==c2);
				//deb(j, dp[j], dp[j]+c+m);
				if(x>dp[j]+c+m){
					x=dp[j]+c+m;
					//ile[i]=ile[j]+1;
				}
			}
			assert(x==dp[i]);
		}*/
		if(ile[n]>k){
			l=m;
			R=mp(ile[n], ll(dp[n]-k*m+0.5));
		}
		else if(ile[n]<k){
			r=m;
			L=mp(ile[n], ll(dp[n]-k*m+0.5));
		}
		else{
			cout<<res+ll(dp[n]-k*m+0.5);
			return 0;
		}
	}
	assert((R.nd*(k-L.st)+L.nd*(R.st-k))%(R.st-L.st)==0);
	ll ans=(R.nd*(k-L.st)+L.nd*(R.st-k))/(R.st-L.st);
	cout<<ans+res;
	//assert(false);
}

컴파일 시 표준 에러 (stderr) 메시지

chorus.cpp:135:4: warning: "/*" within comment [-Wcomment]
  135 |    /*while(opt<i-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...
#Verdict Execution timeMemoryGrader output
Fetching results...