Educational Codeforces Round 171 (Rated for Div. 2)题解记录

比赛链接:https://codeforces.com/contest/2026

A. Perpendicular Segments


题目说了必定有答案,不妨想一想对于\(x,y\)来讲,最大值肯定是相应数构成得正方形得对角线最大,其一定大于等于\(k\),既然最小的正方形满足
直接都取最小的正方形即可(对角线垂直),所以取\(min(x,y)\)

#include<iostream>
#include<queue>
#include<map>
#include<set>
#include<vector>
#include<algorithm>
#include<deque>
#include<cctype>
#include<string.h>
#include<math.h>
#include<time.h>
#include<random>
#include<stack>
#include<string>
#define ll                                    long long 
#define lowbit(x) (x & -x)
using namespace std;
mt19937 rnd(time(0));
const ll mod=1e9+7;
const ll N=2e5+5;
ll ksm(ll x,ll y)
{
	ll ans=1;
	while(y)
	{
		if(y&1)
		ans=(ans%mod*x%mod)%mod;
		x=x%mod*(x%mod)%mod;
		y>>=1;
	}
	return ans%mod%mod;
}
ll gcd(ll x,ll y)
{
	if(y==0)
	return x;
	else 
	return gcd(y,x%y);
}
void fio()
{
		ios::sync_with_stdio(0);
		cin.tie(0);
		cout.tie(0);
}
int main()
{
	fio();
	ll t;
	cin>>t;
	while(t--)
	{
		ll x,y,k;
		cin>>x>>y>>k;
		ll j=min(x,y);
		cout<<0<<" "<<0<<" "<<j<<" "<<j<<endl;
		cout<<j<<" "<<0<<" "<<0<<" "<<j<<endl;
	}
}

B. Black Cells


二分版:

#include<iostream>
#include<queue>
#include<map>
#include<set>
#include<vector>
#include<algorithm>
#include<deque>
#include<cctype>
#include<string.h>
#include<math.h>
#include<time.h>
#include<random>
#include<stack>
#include<string>
#define ll                                    long long 
#define lowbit(x) (x & -x)
using namespace std;
mt19937 rnd(time(0));
const ll mod=1e9+7;
const ll N=2e5+5;
ll ksm(ll x,ll y)
{
	ll ans=1;
	while(y)
	{
		if(y&1)
		ans=(ans%mod*x%mod)%mod;
		x=x%mod*(x%mod)%mod;
		y>>=1;
	}
	return ans%mod%mod;
}
ll gcd(ll x,ll y)
{
	if(y==0)
	return x;
	else 
	return gcd(y,x%y);
}
void fio()
{
		ios::sync_with_stdio(0);
		cin.tie(0);
		cout.tie(0);
}
ll a[250000];
int main()
{
	fio();
	ll t;
	cin>>t;
	while(t--)
	{
		ll n;
		cin>>n;
		if(n==1)
		{
			ll b;
			cin>>b;
			cout<<1<<endl;
			continue;
		}
		for(ll i=1;i<=n;i++)cin>>a[i];
		sort(a+1,a+1+n);
		//a[n+1]=0;
		if(n%2==0)
		{
			ll ans=0;
			for(ll i=1;i<=n-1;i+=2)
			{
				ans=max(ans,a[i+1]-a[i]);
			}
			cout<<ans<<endl;
		}
		else 
		{
			ll l=1,r=1e18;
			while(l<r)
			{
				ll mid=(l+r)>>1;
				ll gs=1;
				ll cnt=0;
				ll pd=0;
				while(gs<=n-1)
				{
					if(a[gs+1]-a[gs]<=mid)
					{
						gs+=2;
						continue;
					}
					else 
					{
						if(cnt==1){
							pd=1;
							break;
						}
						gs++;
						cnt++;
						continue;
					}
				}
					if(pd)
					l=mid+1;
					else 
					r=mid;
			}
			cout<<r<<endl;
		}
	}
}

枚举版:

	#include<iostream>
	#include<queue>
	#include<map>
	#include<set>
	#include<vector>
	#include<algorithm>
	#include<deque>
	#include<cctype>
	#include<string.h>
	#include<math.h>
	#include<time.h>
	#include<random>
	#include<stack>
	#include<string>
	#define ll                                    long long 
	#define lowbit(x) (x & -x)
	using namespace std;
	mt19937 rnd(time(0));
	const ll mod=1e9+7;
	const ll N=2e5+5;
	ll ksm(ll x,ll y)
	{
		ll ans=1;
		while(y)
		{
			if(y&1)
			ans=(ans%mod*x%mod)%mod;
			x=x%mod*(x%mod)%mod;
			y>>=1;
		}
		return ans%mod%mod;
	}
	ll gcd(ll x,ll y)
	{
		if(y==0)
		return x;
		else 
		return gcd(y,x%y);
	}
	void fio()
	{
			ios::sync_with_stdio(0);
			cin.tie(0);
			cout.tie(0);
	}
	ll a[325000];
	int main()
	{
		fio();
		ll t;
		cin>>t;
		while(t--)
		{
			ll n;
			cin>>n;
			for(ll i=1;i<=n;i++)cin>>a[i];
			a[n+1]=0;
			a[n+2]=0;
			ll ans=0;
			if(n%2==0)
			{
				for(ll i=1;i<=n;i+=2)
				{
					ans=max(ans,a[i+1]-a[i]);
				}
			}
			else
			{
				ans=1e18;
				for(ll i=1;i<=n;i+=2)
				{
					ll cnt=0;
					for(ll j=1;j<=n;j+=2)
					{
						if(i==j)cnt=max(cnt,1ll),j++;
						cnt=max(cnt,a[j+1]-a[j]);
					}
					ans=min(ans,cnt);
				}
			}
			cout<<ans<<endl;
		}
	}

C. Action Figures


分析可得0点必选买,非0点优先用0点消除,否则用下标最小的1点消除

#include<iostream>
#include<queue>
#include<map>
#include<set>
#include<vector>
#include<algorithm>
#include<deque>
#include<cctype>
#include<string.h>
#include<math.h>
#include<time.h>
#include<random>
#include<stack>
#include<string>
#define ll                                    long long 
#define lowbit(x) (x & -x)
using namespace std;
mt19937 rnd(time(0));
const ll mod=1e9+7;
const ll N=2e5+5;
ll ksm(ll x,ll y)
{
	ll ans=1;
	while(y)
	{
		if(y&1)
		ans=(ans%mod*x%mod)%mod;
		x=x%mod*(x%mod)%mod;
		y>>=1;
	}
	return ans%mod%mod;
}
ll gcd(ll x,ll y)
{
	if(y==0)
	return x;
	else 
	return gcd(y,x%y);
}
void fio()
{
		ios::sync_with_stdio(0);
		cin.tie(0);
		cout.tie(0);
}
ll a[550000];
int main()
{
	fio();
	ll t;
	cin>>t;
	while(t--)
	{
		ll mo=1;
	ll n;
	cin>>n;
	string f;
	cin>>f;
	set<ll>q,k;
	ll op=0;
	ll ans=0;
	for(ll i=1;i<=n;i++)
	{
		if(f[i-1]=='0')
		q.insert(i);
		else 
		k.insert(i);
	}
	for(ll i=f.size()-1;i>=0;i--)
	{
		if(f[i]=='1')
		{
			ll c=(i+1);
			auto j=k.lower_bound(c);
			if(j!=k.end())
			{
				if(q.size()>0)
				{
					ll u=*q.rbegin();
					q.erase(u);
					ans+=u;
					k.erase(c);
				}
				else
				{
					if(k.size()==1)
					{
						ans+=c;
						k.clear();
					}
					else 
					{
						ll u=*k.begin();
						k.erase(c);
						k.erase(u);
						ans+=u;
					}
				}
			}
		}
		else 
		{
			ll u=i+1;
			if(q.lower_bound(u)!=q.end())
			{
				q.erase(u);
				ans+=u;
			}
		}
		//cout<<ans<<endl;
	}
	cout<<ans<<endl;
	}
}

D. Sums of Segments


优化暴力

#include<iostream>
#include<queue>
#include<map>
#include<set>
#include<vector>
#include<algorithm>
#include<deque>
#include<cctype>
#include<string.h>
#include<math.h>
#include<time.h>
#include<random>
#include<stack>
#include<string>
#define ll                                    long long 
#define lowbit(x) (x & -x)
using namespace std;
mt19937 rnd(time(0));
const ll mod=1e9+7;
const ll N=2e5+5;
ll ksm(ll x,ll y)
{
	ll ans=1;
	while(y)
	{
		if(y&1)
		ans=(ans%mod*x%mod)%mod;
		x=x%mod*(x%mod)%mod;
		y>>=1;
	}
	return ans%mod%mod;
}
ll gcd(ll x,ll y)
{
	if(y==0)
	return x;
	else 
	return gcd(y,x%y);
}
void fio()
{
		ios::sync_with_stdio(0);
		cin.tie(0);
		cout.tie(0);
}
ll a[325000];
ll pre[325000];//一维前缀
ll pre1[325000];//类似二维
ll sub[320555];
ll pre3[325000];
//1 
//1 2
//1 2 5
//1 2 5 10
ll n;
set<pair<ll,ll>>q;
ll qu(ll x)
{
	ll ans=0;
	auto j=q.lower_bound({x,0});
	ll zq=(*j).second;
	ans+=pre3[zq-1];
	j--;
	ll wz=x-(*j).first+zq-1;
	ans+=pre1[zq]-sub[wz+1]-(pre[wz]-pre[zq-1])*(n-zq-(wz-zq));
	return ans;
}
int main()
{
	fio();
	ll t;
	t=1;
	while(t--)
	{
		q.clear();
		cin>>n;
		ll cnt=0;
		for(ll i=1;i<=n;i++)cin>>a[i],pre[i]=pre[i-1]+a[i],cnt+=pre[i];
		pre1[1]=cnt;
		for(ll i=2;i<=n;i++)pre1[i]=pre1[i-1]-(n-i+2)*a[i-1];
		for(ll i=1;i<=n;i++)pre3[i]=pre3[i-1]+pre1[i];
		sub[n+1]=0;
		for(ll i=n;i>=1;i--)sub[i]=sub[i+1]+a[i]*(n-i+1);
		q.insert({0,0});
		 cnt=0;
		for(ll i=1;i<=n;i++)
		{
			cnt+=(n-i+1);
			q.insert({cnt,i});
		}
		ll 	op;
		cin>>op;
		while(op--)
		{
			ll l,r;
			cin>>l>>r;
			cout<<qu(r)-(l-1?qu(l-1):0)<<endl;
		}
	}
}

E. Best Subsequence


题目的意思其实等价于(选的数的个数-选的数中所有二进制存在等于1的不同位置数)
一开始补题,没思路,后面去参考别人题解了。浅学了点网络流最大流,回来一看,确实这个挺板子的
先构建大于0的数和其二进制位置(大于1)的边,然后再构建一个超级源点和大于0的数连边(阈值为1),超级汇点和所有二进制位数的连边(阈值为1)
随后走一遍最大流,然后n-这个最大流即使答案,注意m(浅算一下,最多\(2*(60*100+100+60)\)个边)要开双倍

#include<iostream>
#include<queue>
#include<map>
#include<set>
#include<vector>
#include<algorithm>
#include<deque>
#include<cctype>
#include<string.h>
#include<math.h>
#include<time.h>
#include<random>
#include<stack>
#include<string>
#define ll                                long long 
#define lowbit(x) (x & -x)
using namespace std;
const ll N = 170, M = 16000, INF = 0x3f3f3f3f, mod = 1e9 + 7;
ll n, m, s, t, dis[N], cur[M];//当前弧优化
ll e[M], ne[M], w[M], h[M], idx;
void add(ll l, ll r, ll v)
{
	e[idx] = r;
	w[idx] = v;
	ne[idx] = h[l];
	h[l] = idx++;
}
bool bfs()//分层
{
	queue<ll>q;
	memset(dis, -1, sizeof(dis));
	q.push(s);
	dis[s] = 0;
	cur[s] = h[s];
	while (!q.empty())
	{
		ll u = q.front();
		q.pop();
		for (ll i = h[u]; ~i; i = ne[i])
		{
			ll v = e[i];
			if (dis[v] == -1 && w[i])
			{
				dis[v] = dis[u] + 1;
				cur[v] = h[v];
				if (v == t)
					return 1;
				q.push(v);
			}
		}
	}
	return 0;
}
ll dfs(ll u, ll limit)
{
	if (u == t)
		return limit;
	ll flow = 0;
	for (ll i = cur[u]; ~i; i = ne[i])
	{
		cur[u] = i;
		ll v = e[i];
		if (dis[v] == dis[u] + 1 && w[i])
		{
			ll minf = dfs(v, min(w[i], limit - flow));
			w[i] -= minf;
			w[i ^ 1] += minf;
			flow += minf;
			if (flow == limit)
				return flow;
		}
	}
	return flow;
}
ll dinic()
{
	ll ans = 0;
	while (bfs())
	{
		ans += dfs(s, INF);
	}
	return ans;
}
ll ksm(ll x, ll y)
{
	ll ans = 1;
	while (y)
	{
		if (y & 1)
			ans = (ans % mod * x % mod) % mod;
		x = x % mod * (x % mod) % mod;
		y >>= 1;
	}
	return ans % mod % mod;
}
ll gcd(ll x, ll y)
{
	if (y == 0)
		return x;
	else
		return gcd(y, x % y);
}
void fio()
{
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
}
ll a[250];
int main()
{
	fio();
	ll k;
	cin >> k;
	while (k--)
	{
		idx = 0;
		memset(h, -1, sizeof h);
		cin >> n;
		ll cnt = 0;
		ll ans = 0;
		for (ll i = 1; i <= n; i++)
		{
			ll x;
			cin >> x;
			if (x)cnt++,a[cnt] = x;
		}
		s = n + 63, t = n + 64;
		for (ll i = 1; i <= cnt; i++)
		{
			add(s, i, 1);
			add(i, s, 0);
		}
		for (ll i = 0; i <= 60; i++)
		{
			add(n + i+1, t, 1);
			add(t, n + i+1, 0);
		}
		for (ll i = 1; i <= cnt; i++)
		{
			for (ll j = 0; j <= 60; j++)
			{
				if (a[i] & (1ll << j))
				{
					add(i, n + j+1, 1);
					add(n + j+1, i, 0);
				}
			}
		}
		cout << n - dinic() << endl;
	}
}

posted @ 2024-10-29 13:13  长皆  阅读(312)  评论(0编辑  收藏  举报