Codeforces Round 971 (Div. 4)題解記錄(G3待補)

长皆發表於2024-09-26

A. Minimize!

暴力模擬一遍即可

#include<iostream>
#include<queue>
#include<deque>
#include<map>
#include<set>
#include<stack>
#include<vector>
#include<bitset>
#include<math.h>
#include<random>
#include<string>
#include<string.h>
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
mt19937 rnd(time(0));
const ll mod = 1e9 + 7;
const ll p = rnd();
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 % 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()
{
ll t;
cin>>t;
while(t--)
{
	ll a,b;
	cin>>a>>b;
	ll zm=1561616154;
	for(ll i=a;i<=b;i++)
	{
		zm=min(zm,i-a+b-i);
	}
	cout<<zm<<endl;
} 
}

B. osu!mania

暴力模擬

#include<iostream>
#include<queue>
#include<deque>
#include<map>
#include<set>
#include<stack>
#include<vector>
#include<bitset>
#include<math.h>
#include<random>
#include<string>
#include<string.h>
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
mt19937 rnd(time(0));
const ll mod = 1e9 + 7;
const ll p = rnd();
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 % 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()
{
ll t;
cin>>t;
while(t--)
{
	ll n;
	cin>>n;
	vector<ll>g;
	string f[600];
	for(ll i=1;i<=n;i++)
	{
		cin>>f[i];
	}
	for(ll i=n;i>=1;i--)
	{
		for(ll j=0;j<=3;j++)
		{
			if(f[i][j]=='#')
			{
				g.push_back(j+1);
				break;
			}
		}
	}
	for(auto j:g)
	{
		cout<<j<<" ";
	}
	cout<<endl;
}
}

C. The Legend of Freya the Frog

最大值其實取決於你什麼方向最晚到目標位置
如果是水平方向更大直接兩倍減一
如果是豎直方向直接兩倍即可

#include<iostream>
#include<queue>
#include<deque>
#include<map>
#include<set>
#include<stack>
#include<vector>
#include<bitset>
#include<math.h>
#include<random>
#include<string>
#include<string.h>
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
mt19937 rnd(time(0));
const ll mod = 1e9 + 7;
const ll p = rnd();
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 % 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()
{
ll t;
cin>>t;
while(t--)
{
ll x,y,k;
cin>>x>>y>>k;
ll ans=x/k+(x%k>0);
ll cnt=y/k+(y%k>0);
if(cnt<ans)
{
	cout<<ans+ans-1<<endl;
}
else
{
	cout<<cnt+cnt<<endl;
}
}
}

D. Satyam and Counting

當直角三角形的直角邊不垂直水平方向,直接特判計數
否則直接考慮除了上下兩個點的組合數情況

#include<iostream>
#include<queue>
#include<deque>
#include<map>
#include<set>
#include<stack>
#include<vector>
#include<bitset>
#include<math.h>
#include<random>
#include<string>
#include<string.h>
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
mt19937 rnd(time(0));
const ll mod = 1e9 + 7;
const ll p = rnd();
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 % 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); }
map<pair<ll,ll>,ll>q;
int main()
{
ll t;
cin>>t;
while(t--)
{
	q.clear();
	ll n;
	cin>>n;
	ll ans=0;
	for(ll i=1;i<=n;i++)
	{
		ll x,y;
		cin>>x>>y;
		q[{x,y}]++;
		if(y==0)
		{
			if(q[{x,1}]>0)
			ans+=n-2;
		}
		else
		{
			if(q[{x,0}]>0)
			ans+=n-2;
		}
		if(y==0)
		{
			if(q[{x-1,1}]&&q[{x+1,1}])
			ans++;
			if(q[{x-1,1}]&&q[{x-2,0}])
			ans++;
			if(q[{x+1,1}]&&q[{x+2,0}])
			ans++;
		}
		else
		{
			if(q[{x-1,0}]&&q[{x+1,0}])
			ans++;
			if(q[{x+1,0}]&&q[{x+2,1}])
			ans++;
			if(q[{x-1,0}]&&q[{x-2,1}])
			ans++;
		}
	}
	cout<<ans<<endl;
}
}

E. Klee 的 SUPER DUPER LARGE Array!!

直接二分

#include<iostream>
#include<queue>
#include<deque>
#include<map>
#include<set>
#include<stack>
#include<vector>
#include<bitset>
#include<math.h>
#include<random>
#include<string>
#include<string.h>
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
mt19937 rnd(time(0));
const ll mod = 1e9 + 7;
const ll p = rnd();
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 % 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); }
map<pair<ll,ll>,ll>q;
int main()
{
ll t;
cin>>t;
while(t--)
{
	ll n,k;
	cin>>n>>k;
	ll l=1,r=n;
	ll sum=(k+k+n-1)*n/2;
	while(l<=r)
	{
		ll mid=(l+r)>>1;
		ll u=(k+k+mid-1)*mid/2;
		if(u>=sum-u)
		{
			r=mid-1;
		}
		else
		l=mid+1;
	}
	if(l>1)
	{
		cout<<min(abs((k+(l-2)+k)*(l-1)/2-(sum-(k+(l-2)+k)*(l-1)/2)),abs((k+l-1+k)*l/2-(sum-(k+l-1+k)*l/2)))<<endl;
	}
	else
	cout<<abs((k+l-1+k)*l/2-(sum-(k+l-1+k)*l/2))<<endl;
}
}

F. Firefly's Queries

這裡其實數值和是存在一個週期的,直接左右兩邊儘量縮減然後形成周期的倍數比較好做
本人直接正向暴力了,\(WA\)了三發過

#include<iostream>
#include<queue>
#include<deque>
#include<map>
#include<set>
#include<stack>
#include<vector>
#include<bitset>
#include<math.h>
#include<random>
#include<string>
#include<string.h>
//#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
mt19937 rnd(time(0));
const ll mod = 1e9 + 7;
const ll p = rnd();
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 % 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];
ll n;
ll ans = 0;
ll b[250000];
ll dfs(ll x, ll y)
{
	if (x > y)
		return  15666516;
	//	cout<<x<<" "<<y<<endl;
	ll y1, x1;
	ll u = x / n;//週期數
	ll m = x % n;
	if (x % n == 0)//剛好是這個週期得最後一個
	{
		u--;
		u %= n;
		if (u == 0)//第一週期
			x1 = n;
		else
			x1 = u;
	}
	else
		x1 = u % n + 1;
	u %= n;
	//	cout<<u<<endl;
	if (u == 0)//第0週期特判 
		y1 = n;
	else
		y1 = u;//週期數
	// y1為右約束
	ll g;
	if (y1 >= x1)
		g = 1;
	else
		g = 0;
	ll cnt = 0;
	//	cout<<x1<<" "<<y1<<endl;
	cnt = m;
	if (g == 1)
		x1 += max(cnt-1 , (ll)0);
	else
	{
		if (x1 + cnt-1> n)
			x1 = (x1 + cnt-1) % n,g=1;
		else
			x1 = x1 + cnt-1;
	}
	//cout<<x1<<" "<<y1<<endl;
	ll dis = y - x + 1;
	if (g == 1)
	{
		ans += b[min(x1 + dis - 1, y1)] - b[x1 - 1];
		x += min(dis, y1 - x1 + 1);
	}
	else
	{
		ans += b[min(x1 + dis - 1, n)] - b[x1 - 1];
		x += min(dis, n - x1 + 1);
		x1 = 1;
		if (x <= y)
		{
			dis = y - x + 1;
			ans += b[min(x1 + dis - 1, y1)] - b[x1 - 1];
			x += min(dis, y1 - x1 + 1);
		}
	}
	return x;
}
int main()
{
	fio();
	ll t;
	cin >> t;
	while (t--)
	{
		ll q;
		cin >> n >> q;
		//	cout<<n<<endl;
		ll sum = 0;
		b[0] = 0;
		for (ll i = 1; i <= n; i++)
		{
			cin >> a[i];
			sum += a[i];
			b[i] = b[i - 1] + a[i];
		}
		while (q--)
		{
			ans = 0;
			ll l1, r1;
			cin >> l1 >> r1;
			l1 = dfs(l1, r1);
			//	cout<<l1<<endl;
			if (l1 > r1)
				cout << ans << endl;
			else
			{
				ll l = 0, r = n;
				while (l < r)
				{
					ll mid = (l + r) >> 1;
					if (l1 + mid * n - 1 >= r1)
					{
						r = mid;
					}
					else
						l = mid + 1;
				}
				if (l1 + r * n - 1 == r1)
				{
					cout << ans + r * sum << endl;
				}
				else
				{
					r--;
					ans += r * sum;
					l1 = l1 + r * n - 1;
					l1++;
					ll u = dfs(l1, r1);
					cout << ans << endl;
				}
			}
		}
	}
}

G1. Yunli's Subarray Queries (easy version)

求最長連續的數得先處理一下,直接減(1,2,3,...),因為連續且增大得數差值會變為同一個值,方便統計
然後維護佇列加陣列記錄,這裡加了個大數,使得負數情況消失。空間換時間

#include<iostream>
#include<map>
#include<set>
#include<vector>
#include<string.h>
#include<string>
#include<math.h>
#include<queue>
#include<bitset>
#include<stack>
#include<algorithm>
#include<deque>
using namespace std;
typedef long long ll;
ll a[200005];
ll b[200005];
ll e[400005];//桶排序
ll u[200005];
void fio()
{
	ios::sync_with_stdio();
	cin.tie(0);
	cout.tie(0);
}
int main()
{
	fio();
	ll t;
	cin >> t;
	while (t--)
	{
		priority_queue<pair<ll,ll>>q;
		ll n, k, m;
		cin >> n >> k >> m;
		for (ll i = 1; i <= n; i++)cin >> a[i];
		for (ll i = 1; i <= n; i++)
		{
			b[i] = a[i] - i+200000;//偏差值
		}
		ll l = 0, r = 0;
		for (ll i = 1; i <= n; i++)
		{
			if (l == 0 && r == 0)
			{
				l = r = i;
				e[b[i]]++;//桶排序
				q.push({ e[b[i]],b[i] });
				if (r - l + 1 == k)
					u[l] = q.top().first;
			}
			else
			{
				if (r - l + 1 < k)
				{
					r++;
					e[b[i]]++;
					while (!q.empty() && q.top().first != e[q.top().second])
					{
						q.pop();
					}
					q.push({ e[b[i]],b[i] });
					if (r - l + 1 == k)
						u[l] = q.top().first;
				}
				else if (r - l + 1 == k)
				{
					e[b[l]]--;
					e[b[i]]++;
					while (!q.empty() && q.top().first != e[q.top().second])
					{
						q.pop();
					}
					if (e[b[l]] != 0)
					{
						q.push({ e[b[l]],b[l] });
					}
					q.push({ e[b[i]],b[i] });
					l++;
					r++;
					u[l] = q.top().first;
				}
			}
		}
		for (ll i = 1; i <= n; i++)
		{
			e[b[i]] = 0;
		}
		while (m--)
		{
			ll l, r;
			cin >> l >> r;
			cout << k-u[l] << endl;
		}
	}
}

G2. Yunli's Subarray Queries (hard version)

這裡在G1得基礎上用了堆疊+線段樹
對照過正解,理應後面兩題得用莫隊做

#include<iostream>
#include<map>
#include<set>
#include<vector>
#include<string.h>
#include<string>
#include<math.h>
#include<queue>
#include<bitset>
#include<stack>
#include<algorithm>
#include<deque>
using namespace std;
typedef long long ll;
ll a[200005];
ll b[200005];
ll e[400005];//桶排序
ll u[200005];
ll f[200005];
vector<pair<ll,ll>>g[200005];
struct s
{
	ll l, r;
	ll v, lazy;
}p[250000<<2];
void build(ll i, ll l, ll r)
{
	p[i].l = l;
	p[i].r = r;
	p[i].v=0;
	p[i].lazy = -1;
	if (l == r)
	{
		return;
	}
	build(i << 1, l, (l + r) >> 1);
	build(i << 1 | 1, ((l + r) >> 1)+1, r);
}
void pushdown(ll i)
{
	if (p[i].lazy>=0)
	{
		ll i1 = i << 1, i2 = i << 1 | 1;
		p[i1].v = (p[i1].r - p[i1].l + 1) * p[i].lazy;
		p[i2].v = (p[i2].r - p[i2].l + 1) * p[i].lazy;
		p[i1].lazy = p[i].lazy;
		p[i2].lazy = p[i].lazy;
		p[i].v = p[i1].v + p[i2].v;
		p[i].lazy = -1;
	}
}
void ud(ll i, ll l, ll r,ll x)
{
	if (l == p[i].l && r == p[i].r)
	{
		p[i].v = (p[i].r - p[i].l + 1) * x;
		p[i].lazy = x;
		return;
	}
	pushdown(i);
	ll i1 = i << 1;
	ll i2 = i << 1 | 1;
	if (l <= p[i1].r)
	{
		if (r <= p[i1].r)
		{
			ud(i1, l, r, x);
		}
		else
			ud(i1, l, p[i1].r, x);
	}
	if (r >= p[i2].l)
	{
		if (l >= p[i2].l)
			ud(i2, l, r, x);
		else
			ud(i2, p[i2].l, r, x);
	}
	p[i].v = p[i1].v + p[i2].v;
}
ll query(ll i, ll l, ll r)
{
	ll ans = 0;
	if (l == p[i].l && r == p[i].r)
	{
		ans+=p[i].v;
		return ans;
	}
	pushdown(i);
	ll i1 = i<< 1;
	ll i2 = i << 1 | 1;
	if (l <= p[i1].r)
	{
		if (r <= p[i1].r)
			ans += query(i1, l, r);
		else
			ans += query(i1, l, p[i1].r);
	}
	if (r >= p[i2].l)
	{
		if (l >= p[i2].l)
			ans += query(i2, l, r);
		else
			ans += query(i2, p[i2].l, r);
	}
	return ans;
}
void fio()
{
	ios::sync_with_stdio();
	cin.tie(0);
	cout.tie(0);
}
int main()
{
	fio();
	ll t;
	cin >> t;
	build(1, 1, 200020);
	while (t--)
	{
		priority_queue<pair<ll, ll>>q;
		ll n, k, m;
		cin >> n >> k >> m;
		ud(1, 1, n, 0);
		for (ll i = 1; i <= n; i++)cin >> a[i];
		for (ll i = 1; i <= n; i++)
		{
			b[i] = a[i] - i + 200000;//偏差值
		}
		ll l = 0, r = 0;
		for (ll i = 1; i <= n; i++)
		{
			if (l == 0 && r == 0)
			{
				l = r = i;
				e[b[i]]++;//桶排序
				q.push({ e[b[i]],b[i] });
				if (r - l + 1 == k)
					u[l] = q.top().first;
			}
			else
			{
				if (r - l + 1 < k)
				{
					r++;
					e[b[i]]++;
					while (!q.empty() && q.top().first != e[q.top().second])
					{
						q.pop();
					}
					q.push({ e[b[i]],b[i] });
					if (r - l + 1 == k)
						u[l] = q.top().first;
				}
				else if (r - l + 1 == k)
				{
					e[b[l]]--;
					e[b[i]]++;
					while (!q.empty() && q.top().first != e[q.top().second])
					{
						q.pop();
					}
					if (e[b[l]] != 0)
					{
						q.push({ e[b[l]],b[l] });
					}
					q.push({ e[b[i]],b[i] });
					l++;
					r++;
					u[l] = q.top().first;
				}
			}
		}//處理好了
		for (ll i = 1; i <= n; i++)
		{
			e[b[i]] = 0;
		}
		for (ll i = 1; i <= m; i++)
		{
			ll l, r;
			cin >> l >> r;
			g[l].push_back({ r - k + 1,i });;
		}
		stack<pair<ll,ll>>q1;
		for (ll i = n-k+1; i >= 1; i--)
		{
			u[i] = k - u[i];
			if (q1.empty())
			{
				q1.push({ i,u[i] });
				ud(1, i, i, u[i]);
			}
			else
			{
				ll cnt = i;
				while (!q1.empty() && q1.top().second > u[i])
				{
					cnt = q1.top().first;
					q1.pop();
				}
				ud(1, i, cnt, u[i]);
				q1.push({ cnt,u[i] });
			}
			for (auto j : g[i])
			{
				f[j.second] = query(1, i, j.first);
			}
			g[i].clear();
		}
		for (ll i = 1; i <= m; i++)
		{
			cout << f[i] << endl;
		}
	}
}

G3. Yunli's Subarray Queries (extreme version)

很久沒寫過莫隊了,改天有激情時再補充

相關文章