Codeforces Round 984 (Div. 3)題解記錄(A~F)

长皆發表於2024-11-03

比賽連結:https://codeforces.com/contest/2036

A. Quintomania

思路:資料範圍小+題目清晰,題目要求左右兩個數之差絕對值不等於\(5\)或這不等於\(7\),直接暴力即可,應該不會有人不知到內建函式\(abs\)

#include<iostream>
#include<queue>
#include<map>
#include<set>A~F
#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)
#define endl "\n"//                           互動題記得刪除
using namespace std;
mt19937 rnd(time(0));
const ll mod = 998244353;
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 n;
		cin>>n;
		ll pd=0;
		ll o;
		for(ll i=1;i<=n;i++)
		{
			ll x;
			cin>>x;
			if(i>=2)
			{
				if(abs(o-x)==5||abs(o-x)==7)
				{
					o=x;
				continue;
				}
				pd=1;
			}
			o=x;
		}
		if(pd)
		cout<<"NO"<<endl;
		else 
		cout<<"YES"<<endl;
	}
	
}

B. Startup

思路:一開始看成選(總瓶子大於\(k\)\(k\)個瓶子放在\(n\)個貨架上,然後貨架上的牌子只能是同一種,感覺很難。
隨後發現看錯了,是總共有\(k\)個瓶子,然我放在\(n\)個貨架上,且品牌得一樣,於是直接貪心的把所有品牌對應的值進行累積,
然後進行排序,從大到小選取前\(min(n,牌子種類)\)個即可,本人為了方便直接用了優先對列

#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)
#define endl "\n"//                           互動題記得刪除
using namespace std;
mt19937 rnd(time(0));
const ll mod = 998244353;
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 n,k;
		cin>>n>>k;
		map<ll,ll>mp;
		set<ll>q;
		priority_queue<ll>f;
		for(ll i=1;i<=k;i++)
		{
			ll x,y;
			cin>>x>>y;
			mp[x]+=y;
			q.insert(x);
		}
		for(auto j:q)
		{
			f.push(mp[j]);
		}
		ll ans=0;
		while(!f.empty())
		{
			ans+=f.top();
			f.pop();
			n--;
			if(n==0)
			break;

		}
		cout<<ans<<endl;
	}
}

C. Anya and 1100

思路:對於一個字串有\(q\)次修改,問每次修改後是否存在\(1100\)字串
不妨想想,每次修改一個位置,最多會影響\(4\)個位置的可能,所以直接先暴力統計一開始的所有\(1100\)子串,然後每次修改進行區間\(1100\)變化統計
然後再修改原本的\(1100\)個數就可以了
賽事犯了個低階錯誤,一開始統計\(1100\)直接\(4\)\(4\)個查了。···

#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)
#define endl "\n"//                           互動題記得刪除
using namespace std;
mt19937 rnd(time(0));
const ll mod = 998244353;
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--)
	{
		string f;
		cin>>f;
		ll n=f.size();
		ll q;
		cin>>q;
		ll ans=0;
		f='0'+f;
		for(ll i=1;i<=n-3;i++)
		{
			if(f[i]=='1'&&f[i+1]=='1'&&f[i+2]=='0'&&f[i+3]=='0')
			ans++;
		}
		while(q--)
		{
			ll x;
			char y;
			cin>>x>>y;
			if(n<4)
			{
				cout<<"NO"<<endl;
				continue;
			}
			else 
			{
				ll cnt=0;
				//cout<<n<<endl;
				for(ll i=x-3;i<=x;i++)
				{
					if(i>=1&&i+3<=n)
					{
						if(f[i]=='1'&&f[i+1]=='1'&&f[i+2]=='0'&&f[i+3]=='0')
						cnt++;
					}
				}
				f[x]=y;
				ll uo=0;
				for(ll i=x-3;i<=x;i++)
				{
					if(i>=1&&i+3<=n)
					{
						if(f[i]=='1'&&f[i+1]=='1'&&f[i+2]=='0'&&f[i+3]=='0')
						uo++;
					}
				}
				//cout<<cnt<<endl;
				uo-=cnt;
				ans+=uo;
				if(ans>0)
				cout<<"YES"<<endl;
				else 
				cout<<"NO"<<endl;
			}
		}
	}	
}

D. I Love 1543

思路:其實就是模擬下字串有沒有\(1543\),如何模擬?
首先外圍走一圈順時針是很有格式規定的,於是考慮遞迴寫,然後終止條件可以畫畫,是目前最大行小於等於\(n/2\)或者目前最大列小於等於\(m/2\)
,然後每次縮一次上邊界和下邊界就可以了,統計的話為了方便直接重新進行字串加和,然後再倍增一下,列舉\(0到size()/2-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)
#define endl "\n"//                           互動題記得刪除
using namespace std;
mt19937 rnd(time(0));
const ll mod = 998244353;
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);
}
string f[4000];
ll n,m;
ll ans=0;
void ck(ll x,ll y,ll s,ll p)
{
	if(x<=n/2||y<=m/2)
	return ;
	string u="";
	for(ll j=p;j<=y;j++)
	{
		u+=f[s][j];
	}
	for(ll j=s+1;j<=x;j++)
	{
		u+=f[j][y];
	}
	for(ll j=y-1;j>=p;j--)
	{
		u+=f[x][j];
	}
	for(ll i=x-1;i>=s+1;i--)
	{
		u+=f[i][p];
	}
	//cout<<u<<endl;
	ll k=u.size()-1;
	u+=u;
	for(ll i=0;i<=k;i++)
	{
		if(i+3<=(ll)u.size()-1&&u[i]=='1'&&u[i+1]=='5'&&u[i+2]=='4'&&u[i+3]=='3')
		{
			ans++;
		}
	}
	//cout<<ans<<endl;
	ck(x-1,y-1,s+1,p+1);
}
int main()
{
	fio();
	ll t;
	cin>>t;
	while(t--)
	{
		//ll n,m;
		cin>>n>>m;
		for(ll i=1;i<=n;i++)
		{
			cin>>f[i];
			f[i]='0'+f[i];
		}
		ans=0;
		ck(n,m,1,1);
		cout<<ans<<endl;
	}	
}

E. Reverse the Rivers

思路:\(n*k<=10^5\),所以在\(main\)函式內定義二維陣列,然後先按照題目要求進行處理或之和(兩個數之或一定不變或者增加,所以或之和是不遞減的,具有單調性),然後再用一個陣列以列為第一維行為第二維統計每行對應的數,然後有\(q\)次詢問,但是注意\(m<=10^5\),所以其實也就最多有\(m\)個約束。因為題目要求找到合理的最小序號,所以要用\(l,r\)雙指標進行區間維護,對於\(<\),可以用\(lower_bound\)找到第一個大於等於\(y\)的行\(c\),然後\(c--\),取\(r=min(r,c)\),對於\(>\),可以用\(upper_bound\)直接找到對應的行\(c\),然後取\(l=max(l,c)\)即可,如果\(l>r\),輸出\(-1\),否則輸出\(l\)

#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)
#define endl "\n"//                           互動題記得刪除
using namespace std;
mt19937 rnd(time(0));
const ll mod = 998244353;
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()
{
	ll t;
	t=1;
	while(t--)
	{
		ll n,k,q;
		cin>>n>>k>>q;
		ll a[n+5][k+5];
		for(ll i=0;i<=n;i++)
		{
			for(ll j=0;j<=k;j++)
			{
				a[i][j]=0;
			}
		}
		for(ll i=1;i<=n;i++)
		{
			for(ll j=1;j<=k;j++)
			{
				cin>>a[i][j];
			}
		}
		//cout<<a[0][1]<<endl;
		ll b[k+5][n+5]={0};
		for(ll j=1;j<=k;j++)
		{
			for(ll i=1;i<=n;i++)
			{
				a[i][j]=(a[i][j]|a[i-1][j]);
				b[j][i]=a[i][j];
				//cout<<a[i][j]<<endl;
			}
		}
		//cout<<b[1][2]<<endl;
		while(q--)
		{
			ll m;
			cin>>m;
			ll l=1,r=n;
			for(ll i=1;i<=m;i++)
			{
				ll x,y;
				char f;
				cin>>x>>f>>y;
				if(f=='<')
				{
					ll u=lower_bound(b[x]+1,b[x]+1+n,y)-b[x];
					u--;
					r=min(r,u);
				}
				else 
				{
					ll u=upper_bound(b[x]+1,b[x]+1+n,y)-b[x];
					l=max(l,u);
				}
			}
			if(l>r)
			{
				cout<<-1<<endl;
			}
			else 
			cout<<l<<endl;
		}
	}
}

F. XORificator 3000

思路:賽時沒考慮r<k時直接輸出答案,一直WA2
其實對於一個從1開始的連續區間的異或和,其答案是有規律的
規律如下:
\(n%4==0\)
\(f(1,n)=n\)
\(n%4==1\)
\(f(1,n)=1\)
\(n%4==2\):
\(f(1,n)=n+1\)
\(n%4==3\):
\(f(1,n)=0\)
顯然對於\(f(l,r)\)\(f(l,r)=f(1,r)^f(1,l-1)\)
隨後如何處理不合理答案
其實容易發現對於\(2^i\)乘連續數的答案的異或之和會等於連續的數的異或之和乘以\(2^i\)
所以解決了\(2^i\)的問題然後是對於\(k\),他其實一直在異或自己,如果異或了自己偶數次,則為\(0\),否則為本身,這個的次數奇偶性等於區間\(2^i*b+k\),\(b\)的可能個數的奇偶性
最後處理好是否異或\(k\)就行了,注意特判情況\(r<k\)

#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                                     __int64
#define lowbit(x) (x & -x)
#define endl "\n"//                           互動題記得刪除
using namespace std;
mt19937 rnd(time(0));
const ll mod = 998244353;
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 ck(ll r)
{
	if(r%4==0)
	{
	return r;
	}
		else if(r%4==1)
		{
			return 1;
		}
		else if(r%4==2)
		{
			return r+1;
		}
		else 
		{
			return 0;
		}
}
int main()
{
	ll t;
	cin>>t;
	while(t--)
	{
		ll l,r,f,k;
		cin>>l>>r>>f>>k;
		ll ans=0;
		ans=(ck(r)^ck(l-1));
		if(r<k)
		{
			cout<<ans<<endl;
			continue;
		}
		//cout<<ans<<endl;
		ll u=1<<f;
		ll l1=(l-k)/u+((l-k)%u>0);
		ll r1=(r-k)/u;
		ll op;
		op=ck(r1)^ck(l1-1);
		op*=u;
		ans^=op;
		if((r1-l1+1)%2==0)
		cout<<ans<<endl;
		else 
		{
		cout<<(ans^k)<<endl;
		}
	}
}

相關文章