CF edu 168 題解

wangmarui發表於2024-07-31

A

直接找兩個相同的字元往裡面塞個不同的字元即可。

點選檢視程式碼
/*
Tips:

你陣列開小了嗎?
你MLE了嗎?
你覺得是貪心,是不是該想想dp?
一個小時沒調出來,是不是該考慮換題?
打 cf 不要用 umap!!!

記住,rating 是身外之物。

該衝正解時衝正解!

Problem:

演算法:

思路:

*/
#include<bits/stdc++.h>
using namespace std;
//#define map unordered_map
#define re register
#define ll long long
#define forl(i,a,b) for(re ll i=a;i<=b;i++)
#define forr(i,a,b) for(re ll i=a;i>=b;i--)
#define forll(i,a,b,c) for(re ll i=a;i<=b;i+=c)
#define forrr(i,a,b,c) for(re ll i=a;i>=b;i-=c)
#define mid ((l+r)>>1)
#define lowbit(x) (x&-x)
#define pb push_back
#define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);init();
#define endl '\n'
#define QwQ return 0;
#define db long double
#define ull unsigned long long
#define lcm(x,y) x/__gcd(x,y)*y
#define Sum(x,y) 1ll*(x+y)*(y-x+1)/2
#define x first
#define y second
#define aty cout<<"Yes\n";
#define atn cout<<"No\n";
#define cfy cout<<"YES\n";
#define cfn cout<<"NO\n";
#define xxy cout<<"yes\n";
#define xxn cout<<"no\n";
#define printcf(x) x?cout<<"YES\n":cout<<"NO\n";
#define printat(x) x?cout<<"Yes\n":cout<<"No\n";
#define printxx(x) x?cout<<"yes\n":cout<<"no\n";
#define maxqueue priority_queue<ll>
#define minqueue priority_queue<ll,vector<ll>,greater<ll>>
void Max(ll&x,ll y){x=max(x,y);}
void Min(ll&x,ll y){x=min(x,y);}
ll _t_;
void _clear(){}
void solve()
{
	_clear();
	string s;
	cin>>s;
	ll n=s.size();
	s=' '+s;
	forl(i,1,n-1)
	{
		if(s[i]==s[i+1])
		{
			if(s[i]=='a')
			{
				forl(j,1,i)
					cout<<s[j];
				cout<<'b';
				forl(j,i+1,n)
					cout<<s[j];
				cout<<endl;
			}
			else
			{
				forl(j,1,i)
					cout<<s[j];
				cout<<'a';
				forl(j,i+1,n)
					cout<<s[j];
				cout<<endl;			
			}
			return ;
		}
	}
	forl(i,1,n)
		cout<<s[i];
	if(s[n]=='a')
		cout<<'b';
	else
		cout<<'a';
	cout<<endl;
}
void init(){}
int main()
{
	IOS;
	_t_=1;
 	cin>>_t_;
	while(_t_--)
		solve();
	QwQ;
}

B

直接暴力判斷用字首和維護即可。

點選檢視程式碼
/*
Tips:

你陣列開小了嗎?
你MLE了嗎?
你覺得是貪心,是不是該想想dp?
一個小時沒調出來,是不是該考慮換題?
打 cf 不要用 umap!!!

記住,rating 是身外之物。

該衝正解時衝正解!

Problem:

演算法:

思路:

*/
#include<bits/stdc++.h>
using namespace std;
//#define map unordered_map
#define re register
#define ll long long
#define forl(i,a,b) for(re ll i=a;i<=b;i++)
#define forr(i,a,b) for(re ll i=a;i>=b;i--)
#define forll(i,a,b,c) for(re ll i=a;i<=b;i+=c)
#define forrr(i,a,b,c) for(re ll i=a;i>=b;i-=c)
#define mid ((l+r)>>1)
#define lowbit(x) (x&-x)
#define pb push_back
#define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);init();
#define endl '\n'
#define QwQ return 0;
#define db long double
#define ull unsigned long long
#define lcm(x,y) x/__gcd(x,y)*y
#define Sum(x,y) 1ll*(x+y)*(y-x+1)/2
#define x first
#define y second
#define aty cout<<"Yes\n";
#define atn cout<<"No\n";
#define cfy cout<<"YES\n";
#define cfn cout<<"NO\n";
#define xxy cout<<"yes\n";
#define xxn cout<<"no\n";
#define printcf(x) x?cout<<"YES\n":cout<<"NO\n";
#define printat(x) x?cout<<"Yes\n":cout<<"No\n";
#define printxx(x) x?cout<<"yes\n":cout<<"no\n";
#define maxqueue priority_queue<ll>
#define minqueue priority_queue<ll,vector<ll>,greater<ll>>
void Max(ll&x,ll y){x=max(x,y);}
void Min(ll&x,ll y){x=min(x,y);}
ll _t_;
void _clear(){}
ll n;
ll pd;
string s[10];
ll sum[200010],sum2[200010];
ll sum3[200010],sum4[200010];
void solve()
{
	pd=1;
	_clear();
	cin>>n>>s[1]>>s[2];
	forl(i,0,n+2)
		sum[i]=sum2[i]=sum3[i]=sum4[i]=0;
	s[1]=' '+s[1];
	s[2]=' '+s[2];
	forl(j,1,2)
		forl(i,1,n)
			pd&=s[j][i]=='x';
	forl(i,1,n)
		sum[i]|=s[1][i]=='.',sum2[i]=sum[i];
	forl(i,1,n)
		sum[i]|=sum[i-1];
	forr(i,n,1)
		sum2[i]|=sum2[i+1];
	forl(i,1,n)
		sum3[i]|=s[2][i]=='.',sum4[i]=sum3[i];
	forl(i,1,n)
		sum3[i]|=sum3[i-1];
	forr(i,n,1)
		sum4[i]|=sum4[i+1];		
	if(pd==1)
	{
		cout<<0<<endl;
		return ; 
	}
	ll ans=0;
	forl(i,1,n)
		if(s[2][i-1]=='x' && s[2][i]=='.' && s[2][i+1]=='x' && (sum[i-1] || sum3[i-2]) && (sum2[i+1] || sum4[i+2]))
			ans++;
	forl(i,1,n)
		if(s[1][i-1]=='x' && s[1][i]=='.' && s[1][i+1]=='x' && (sum[i-2] || sum3[i-1]) && (sum2[i+2] || sum4[i+1]))
			ans++;
	cout<<ans<<endl;
}
void init(){}
int main()
{
	IOS;
	_t_=1;
 	cin>>_t_;
	while(_t_--)
		solve();
	QwQ;
}

C

右括號合法情況下能放就放,剩餘情況放左括號即可。

點選檢視程式碼
/*
Tips:

你陣列開小了嗎?
你MLE了嗎?
你覺得是貪心,是不是該想想dp?
一個小時沒調出來,是不是該考慮換題?
打 cf 不要用 umap!!!

記住,rating 是身外之物。

該衝正解時衝正解!

Problem:

演算法:

思路:

*/
#include<bits/stdc++.h>
using namespace std;
//#define map unordered_map
#define re register
#define ll long long
#define forl(i,a,b) for(re ll i=a;i<=b;i++)
#define forr(i,a,b) for(re ll i=a;i>=b;i--)
#define forll(i,a,b,c) for(re ll i=a;i<=b;i+=c)
#define forrr(i,a,b,c) for(re ll i=a;i>=b;i-=c)
#define mid ((l+r)>>1)
#define lowbit(x) (x&-x)
#define pb push_back
#define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);init();
#define endl '\n'
#define QwQ return 0;
#define db long double
#define ull unsigned long long
#define lcm(x,y) x/__gcd(x,y)*y
#define Sum(x,y) 1ll*(x+y)*(y-x+1)/2
#define x first
#define y second
#define aty cout<<"Yes\n";
#define atn cout<<"No\n";
#define cfy cout<<"YES\n";
#define cfn cout<<"NO\n";
#define xxy cout<<"yes\n";
#define xxn cout<<"no\n";
#define printcf(x) x?cout<<"YES\n":cout<<"NO\n";
#define printat(x) x?cout<<"Yes\n":cout<<"No\n";
#define printxx(x) x?cout<<"yes\n":cout<<"no\n";
#define maxqueue priority_queue<ll>
#define minqueue priority_queue<ll,vector<ll>,greater<ll>>
void Max(ll&x,ll y){x=max(x,y);}
void Min(ll&x,ll y){x=min(x,y);}
ll _t_;
void _clear(){}
ll n;
ll pd;
string s[10];
ll sum[200010],sum2[200010];
ll sum3[200010],sum4[200010];
void solve()
{
	pd=1;
	_clear();
	cin>>n>>s[1]>>s[2];
	forl(i,0,n+2)
		sum[i]=sum2[i]=sum3[i]=sum4[i]=0;
	s[1]=' '+s[1];
	s[2]=' '+s[2];
	forl(j,1,2)
		forl(i,1,n)
			pd&=s[j][i]=='x';
	forl(i,1,n)
		sum[i]|=s[1][i]=='.',sum2[i]=sum[i];
	forl(i,1,n)
		sum[i]|=sum[i-1];
	forr(i,n,1)
		sum2[i]|=sum2[i+1];
	forl(i,1,n)
		sum3[i]|=s[2][i]=='.',sum4[i]=sum3[i];
	forl(i,1,n)
		sum3[i]|=sum3[i-1];
	forr(i,n,1)
		sum4[i]|=sum4[i+1];		
	if(pd==1)
	{
		cout<<0<<endl;
		return ; 
	}
	ll ans=0;
	forl(i,1,n)
		if(s[2][i-1]=='x' && s[2][i]=='.' && s[2][i+1]=='x' && (sum[i-1] || sum3[i-2]) && (sum2[i+1] || sum4[i+2]))
			ans++;
	forl(i,1,n)
		if(s[1][i-1]=='x' && s[1][i]=='.' && s[1][i+1]=='x' && (sum[i-2] || sum3[i-1]) && (sum2[i+2] || sum4[i+1]))
			ans++;
	cout<<ans<<endl;
}
void init(){}
int main()
{
	IOS;
	_t_=1;
 	cin>>_t_;
	while(_t_--)
		solve();
	QwQ;
}

D

二分答案。

可以逐一計算每個節點在節點一最終為 \(Mid\) 時的所需要的付出的代價,可以透過 dfs 來進行代價的下傳。

時間複雜度 \(O(n \log V)\)。其中 \(V\) 為答案的上界。

點選檢視程式碼
/*
Tips:

你陣列開小了嗎?
你MLE了嗎?
你覺得是貪心,是不是該想想dp?
一個小時沒調出來,是不是該考慮換題?
打 cf 不要用 umap!!!

記住,rating 是身外之物。

該衝正解時衝正解!

Problem:

演算法:

思路:

*/
#include<bits/stdc++.h>
using namespace std;
//#define map unordered_map
#define re register
#define ll long long
#define forl(i,a,b) for(re ll i=a;i<=b;i++)
#define forr(i,a,b) for(re ll i=a;i>=b;i--)
#define forll(i,a,b,c) for(re ll i=a;i<=b;i+=c)
#define forrr(i,a,b,c) for(re ll i=a;i>=b;i-=c)
#define mid ((l+r)>>1)
#define lowbit(x) (x&-x)
#define pb push_back
#define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);init();
#define endl '\n'
#define QwQ return 0;
#define db long double
#define ull unsigned long long
#define lcm(x,y) x/__gcd(x,y)*y
#define Sum(x,y) 1ll*(x+y)*(y-x+1)/2
#define x first
#define y second
#define aty cout<<"Yes\n";
#define atn cout<<"No\n";
#define cfy cout<<"YES\n";
#define cfn cout<<"NO\n";
#define xxy cout<<"yes\n";
#define xxn cout<<"no\n";
#define printcf(x) x?cout<<"YES\n":cout<<"NO\n";
#define printat(x) x?cout<<"Yes\n":cout<<"No\n";
#define printxx(x) x?cout<<"yes\n":cout<<"no\n";
#define maxqueue priority_queue<ll>
#define minqueue priority_queue<ll,vector<ll>,greater<ll>>
void Max(ll&x,ll y){x=max(x,y);}
void Min(ll&x,ll y){x=min(x,y);}
ll _t_;
void _clear(){}
ll n;
ll a[200010];
vector<ll>G[200010];
ll L,R;
ll fl;
ll x,y;
void dfs(ll x,ll fa,ll need)
{
	if(need>1e17)
	{
		fl=0;
		return ;
	}
	ll pd=0;
	for(auto i:G[x])
		if(i!=fa)
			pd=1,dfs(i,x,need+max(0ll,need-a[x]));
//	cout<<x<<' '<<fa<<' '<<need;
	if(pd==0 && a[x]<need)
	{
//		need=max(need-a[x],0ll);
		fl=0;
	}
}
bool check(ll x)
{
	fl=1;
	for(auto i:G[1])
		dfs(i,1,x-a[1]);
	return fl;
}
void solve()
{
	_clear();
	cin>>n;
	forl(i,0,n+2)
		G[i].clear();
	forl(i,1,n)
		cin>>a[i];
	forl(i,2,n)
		cin>>x,G[x].pb(i),G[i].pb(x);
	L=0,R=1e10;
	while(L<R)
	{
		ll Mid=(L+R+1)/2;
		if(check(Mid))
			L=Mid;
		else
			R=Mid-1;
	}
	cout<<L<<endl;
}
void init(){}
int main()
{
	IOS;
	_t_=1;
 	cin>>_t_;
	while(_t_--)
		solve();
	QwQ;
}

E

/fn /fn /fn /fn /fn /fn /fn /fn /fn /fn /fn

根號分治。

設闕值 \(B\)\(\sqrt{n}\),我們可以將所有小於等於 \(B\)\(k\) 的全部答案都預處理出來,反之可以透過預處理 \(sum_{i,j}\) 表示前 \(i\) 個人戰鬥力大於等於 \(j\) 的人的個數,然後就可以進行二分了。

但是你會發現,這個做法空間是剛好不夠開的,於是你空間不夠開的部分,直接暴力求,就可以透過本題了。

時間複雜度 \(O(n \sqrt{n} \log n)\)

點選檢視程式碼
/*
Tips:

你陣列開小了嗎?
你MLE了嗎?
你覺得是貪心,是不是該想想dp?
一個小時沒調出來,是不是該考慮換題?
打 cf 不要用 umap!!!

記住,rating 是身外之物。

該衝正解時衝正解!

Problem:

演算法:

思路:

*/
#include<bits/stdc++.h>
using namespace std;
//#define map unordered_map
#define re register
#define ll int
#define forl(i,a,b) for(re ll i=a;i<=b;i++)
#define forr(i,a,b) for(re ll i=a;i>=b;i--)
#define forll(i,a,b,c) for(re ll i=a;i<=b;i+=c)
#define forrr(i,a,b,c) for(re ll i=a;i>=b;i-=c)
#define mid ((l+r)>>1)
#define lowbit(x) (x&-x)
#define pb push_back
#define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);init();
#define endl '\n'
#define QwQ return 0;
#define db long double
#define ull unsigned long long
#define lcm(x,y) x/__gcd(x,y)*y
#define Sum(x,y) 1ll*(x+y)*(y-x+1)/2
#define x first
#define y second
#define aty cout<<"Yes\n";
#define atn cout<<"No\n";
#define cfy cout<<"YES\n";
#define cfn cout<<"NO\n";
#define xxy cout<<"yes\n";
#define xxn cout<<"no\n";
#define printcf(x) x?cout<<"YES\n":cout<<"NO\n";
#define printat(x) x?cout<<"Yes\n":cout<<"No\n";
#define printxx(x) x?cout<<"yes\n":cout<<"no\n";
#define maxqueue priority_queue<ll>
#define minqueue priority_queue<ll,vector<ll>,greater<ll>>
void Max(ll&x,ll y){x=max(x,y);}
void Min(ll&x,ll y){x=min(x,y);}
ll _t_;
void _clear(){}
ll n,q,sq;
ll a[200010];
ll vis[200010][320];
ll sum[200010][320];
ll get(ll l,ll r,ll x)
{
	ll su=0;
	forl(i,l,r)
		su+=a[i]>=x;
	return su;
}
ll x,y;
void solve()
{
	_clear();
	cin>>n>>q;
	sq=sqrt(n);
	Min(sq,317);
	forl(i,1,n)
	{
		cin>>a[i];
		forl(j,0,sq+1)
		{
			sum[i][j]=sum[i-1][j];
			if(a[i]>=j)
				sum[i][j]++;
		}
	}
	forl(i,1,sq)
	{
		ll sum=1,sum2=0;
		forl(j,1,n)
		{
			if(sum>a[j])
				continue;
			vis[j][i]=1;
			sum2++;
			if(sum2==i)
			{
				sum2=0;
				sum++;
			}
		}
	}
	while(q--)
	{
		cin>>x>>y;
		if(y<=sq)
		{
			printcf(vis[x][y]);
			continue;
		}
		ll now=1,sum2=1;
		forl(i,1,n)
		{
			ll L=now+y-1,R=n;
			while(L<R)
			{
				ll Mid=(L+R)/2;
				if(sum2<=sq)
				{ 
					if(sum[Mid][sum2]-sum[now-1][sum2]<y)
						L=Mid+1;
					else
						R=Mid;
				}
				else
				{
					if(get(now,Mid,sum2)<y)
						L=Mid+1;
					else
						R=Mid;
				}
			}
			sum2++;
			now=L+1;
			if(L>=x)
			{
				printcf(a[x]>=sum2-1);
				break;
			}
		}
	}
}
void init(){}
int main()
{
	IOS;
	_t_=1;
 //	cin>>_t_;
	while(_t_--)
		solve();
	QwQ;
}

根號分治