周总结

我按照时间从近到远的顺序写的

1.友谊赛 (2/9)

打的一坨,感觉最近状态不是很好,需要调整一下把心态正回来,要更加专注才行。

B - Reserve or Reverse

注意读题,不是替换区间的字符串,而是替换字符,并且题目的要求是替换的区间是越来越小的

,意思就是替换的字符区间会缩小。我的写法是用mutilset从小到大记录,然后用头去比较,

如果头不是最小就跟他换,set里面的最小是rfind()去找的,然后为了让区间变小,我把大于前面

出现过的区间最小的全部丢掉。但是这样操作是有问题的。正确做法应该是让区间不断减小,如果左边大于右边

就让右边大于左边的字符在set里面删除,直到小于为止,然后替换,替换之后,这两个数也不能用在set中erase,l++,r--,

直到l>=r就break;

#include <bits/stdc++.h>
using namespace std;
multiset<char>st;
int main(){
	int n;
	cin>>n;
	string s;
	cin>>s;
	for(int i=0;i<n;i++){
		st.insert(s[i]);
	}
	int l=0,r=n-1;
	while(l<r){
		if(s[l]!=*st.begin()){
			while(s[r]!=*st.begin()){
				st.erase(st.find(s[r]));
				r--;
			}
			swap(s[l],s[r]);
			st.erase(st.find(s[l]));
			l++;
			st.erase(st.find(s[r]));
			r--;
			
		}else{
			st.erase(st.find(s[l]));
			l++;
		}
	}
	cout<<s;
}

A.Tiling Challenge

牛魔题,搞我心态,题读错了,我读成有无十字的.以及有十字的点的话他们有没有重复出现的点。

题目的意思是:能不能把所有的.换成#。。。服了

最近在练dfs,就直接dfs扫了一遍wa8了,后面用两重for就过了。

#include <bits/stdc++.h>
using namespace std;
int n;
char v[51][51];
int vis[51][51];
bool judge(int x, int y) {
	if (x <= 1 || x >= n || y <= 1 || y >= n) return false;
	if (v[x][y] == '.' && v[x - 1][y] == '.' && v[x + 1][y] == '.' && v[x][y - 1] == '.' && v[x][y + 1] == '.') return true;
	return false;
}
int main() {
	cin >> n;
	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= n; j++) {
			cin >> v[i][j];
		}
	}
	int ans=0;
	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= n; j++) {
			if (judge(i, j)) {
				ans++;
				v[i][j]='#';
				v[i - 1][j]='#';
				v[i + 1][j] ='#';
				v[i][j - 1] ='#';
				v[i][j + 1] ='#';
			}
		}
	}
	if(ans!=0){
		for (int i = 1; i <= n; i++) {
			for (int j = 1; j <= n; j++) {
				if (v[i][j] == '.') {
					cout << "NO";
					return 0;
				}
			}
		}
		cout << "YES";
	}else 
		cout<<"NO";
	return 0;
}

D - All Assign Point Add

这道题就是考怎么去思考快速给数组全部赋值,我一开始打算用fill和vector直接赋值,全部超时了。

后面是这样去思考的,每一次全部赋值,如果这个值后面没有修改过,就一直是被赋值的数,修改了,还需要判断有没有被赋值过,如果没有

被赋值过,需要先赋值再加,如果已经赋值了,那就直接加上新的值,输出的值也要判断一下,赋值刷新了并且修改的,赋值没有修改的,没有赋值的

三类讨论一下就行。

#include <bits/stdc++.h>

using namespace std;

long long n;
vector<long long> v;
set<long long>st;
int main() {
	ios::sync_with_stdio(false); 
	cin.tie(nullptr); 
	
	cin >> n;
	v.resize(n + 1); 
	for (int i = 1; i <= n; i++) {
		cin >> v[i];
	}
	long long q;
	int pd=0;
	long long w=0;
	cin >> q;
	while (q--) {
		long long x, y, z;
		cin >> x;
		if (x == 1) {
			cin >> y;
			pd=1;
			w=y;
			st.clear();
		} else if (x == 2) {
			cin >> y >> z;
			if(pd==1&&st.find(y)==st.end()){
				v[y]=w;
				st.insert(y);
			}
			v[y] += z;
		
		} else {
			cin >> y;
			if(pd==1&&st.find(y)==st.end())
				cout <<	w << '\n';
			else if(pd==1&&st.find(y)!=st.end()){
				cout<<v[y]<<'\n';
			}else
				cout<<v[y]<<'\n';
		}
	}
}

D. Walk on Matrix

构造题,我的噩梦

首先我们可以想怎么去构造一个满足条件的通解。

注意构造题,我们尽量去找通解。

如果是2x3的矩阵,

我们找一个2的几次方大于3*10的5次方的数

再找一个小于它的数

排列起来是

2 1 0

n 2 n

只有三条路

1 & N = 0

2 & N = N

走2那条路

#include<bits/stdc++.h>
using namespace std;
#define int long long
/*
  https://codeforces.com/problemset/problem/1503/B

  
 */
#define endl '\n'
typedef pair<int,int> pii;
typedef unsigned long long ull;
typedef long long ll;
const int N = 2e5+5,M=20,mod=998244353,P=131,INF=2e9;
int ans[3][2];
void solve(){
	int k;
	cin>>k;
	int s=0,p=k;
	while(p){
	s++;
		p>>=1;
	}
	cout<<3<<" "<<2<<endl;
	ans[0][0]=(1<<s+1)-1;
	ans[0][1]=k;
	ans[1][0]=1<<s;
	ans[1][1]=(1<<s+1)-1;
	ans[2][1]=(1<<s)-1;
	for(int i=0;i<3;i++){
	for(int j=0;j<2;j++){
		cout<<ans[i][j]<<" ";
	}
	cout<<endl;
	}
}
void fast(){
	ios::sync_with_stdio(false);
	cin.tie(0),cout.tie(0);
}
signed main(){
	fast();
	int t=1;
//   cin>>t;
	while(t--)solve();
	return 0;
}
  1. SMU Summer 2024 Contest Round 5(3/7)

Robot Takahashi

按照 Wi排个序,算一下前缀后缀 1 和 0 的个数就行了。答案大概是一个 max(pi+si+1)的形式。

有一个小细节:排序之后 Wi=Wi+1时无法在 i,i+1之间断开,要特判。我因为这个 WA 了一发。

#include<bits/stdc++.h>

#define int long long

using namespace std;

inline int read(){
	int x=0,f=1;char c=getchar();
	for(;(c<'0'||c>'9');c=getchar()){if(c=='-')f=-1;}
	for(;(c>='0'&&c<='9');c=getchar())x=x*10+(c&15);
	return x*f;
}

const int MN=2e5+5;
int n,ans;
string s;
struct Node{int v,p;}a[MN];
int pre[MN],suf[MN];

signed main(void){
	
	cin>>n>>s;
	for(int i=1;i<=n;i++)cin>>a[i].v,a[i].p=(s[i-1]=='1');
	sort(a+1,a+n+1,[](const Node &x,const Node &y){
		return x.v<y.v;
	});
	for(int i=1;i<=n;i++)pre[i]=pre[i-1]+(a[i].p==0);
	for(int i=n;i>=1;i--)suf[i]=suf[i+1]+(a[i].p==1);
	for(int i=0;i<=n;i++){
		if(a[i].v!=a[i+1].v){
				ans=max(ans,pre[i]+suf[i+1]);
		}
		
	}
	cout<<ans<<endl;
	
	return 0;
}

Connect 6

暴力题。。。

#include <bits/stdc++.h>

using namespace std;

using ll =long long;

ll n,m,t;


	vector<string>v(100010);
ll a[1000010];
void solve(){
	cin>>n;

	for(int i=0;i<n;i++){
		cin>>v[i];
	}
	for(int i=0;i<n;i++){
		for(int j=0;j<n;j++){
				int pd=0;
				for(int k=j;k<=j+5;k++){
					if(k<n){
					if(v[i][k]=='#')pd++;
					 if(pd>=4){
						cout<<"Yes";
						return;
						}
					}
				}
					 pd=0;
				for(int k=i;k<=i+5;k++){
						if(k<n){
					if(v[k][j]=='#')pd++;
					 if(pd>=4){
						cout<<"Yes";
						return;
						}
					}
				}
					 pd=0;
			for(int k=0;k<=5;k++){
				if(i+5<n&&j+5<n){
					if(v[i+k][j+k]=='#')pd++;
					if(pd>=4){
						cout<<"Yes";
						return;
					}
				}
			}
					 pd=0;
				for(int k=0;k<=5;k++){
					if(i-5>=0&&j+5<n){
						if(v[i-k][j+k]=='#')pd++;
						if(pd>=4){
							cout<<"Yes";
							return;
						}
					}
				
				}				
			}
	}
	cout<<"No";
}

int main(){
	ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
	int t=1;
	//cin>>t;
	while(t--){
		solve();
	}
	return 0;
}

Strange Balls

赛时看不懂题目,赛后也想了很久才明白,有点像栈,它的意思是存数像栈一样,当n个数上的n个球时,

就会删除,然后问你每次添加球后的状态------个数,我们每次存进去个数,相同加加,不相同就push下一个,如果当前

个数达到n个,就把stack最顶上的pop掉,以此类推。

#include<bits/stdc++.h>
using namespace std;
#define int long long
const int mxn=1e6+10;
const int mxe=1e6+10;
const int Inf=1e18;

stack<pair<int,int> > S;
int n;
int a[mxn];
void solve(){
	cin>>n;
	for(int i=1;i<=n;i++) cin>>a[i];
	int cnt=0;
	for(int i=1;i<=n;i++){
		if(S.empty()){
			S.push({a[i],1});
			cnt++;
		}else if(S.top().first==a[i]){
			S.top().second++;
			cnt++;
			if(S.top().second==a[i]){
				cnt-=a[i];
				S.pop();
			}
		}else{
			S.push({a[i],1});
			cnt++;
		}
		cout<<cnt<<'\n';
	}
}
signed main(){
	ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
	int t=1;//cin>>__;
	while(t--)solve();return 0;
}

Linear Probing

思路:为了快速获得x位置之后第一个为-1的数,考虑使用并查集,连通当前点和下一个点的最前面点。

#include <bits/stdc++.h>
#define IOS ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
#define endl "\n"
#define LL long long
using namespace std;
const int N = 2e6 + 10, MOD = 1048576;
int Q;
LL p[N], v[N];
int find(int x)
{
	if (p[x] != x)	p[x] = find(p[x]);
	return p[x];
}
int main() {
	IOS;
	for (int i = 0; i < 1048576; i ++ )	p[i] = i, v[i] = -1;
	cin >> Q;
	while (Q -- ) {
		int t;
		LL x;
		cin >> t >> x;
		if (t == 1)	{
			LL k = find(x % MOD);
			v[k] = x;
			p[k] = (k + 1) % MOD;
		}
		else cout << v[x % MOD] << endl;
	}
	return 0;
}
  1. SMU Summer 2024 Contest Round 4

Made Up

问你Bci=Ai,就是有多少个c下标的b数组里面多少个和a相等。用一个map存数量就行。

#include <bits/stdc++.h>
using namespace std;
using ll =long long;
ll n;
ll a[100010];
ll b[100010];
ll c[100010];
map<ll,ll>mp;
int main(){
	cin>>n;
	for(int i=1;i<=n;i++)cin>>a[i];
	for(int i=1;i<=n;i++)cin>>b[i];
	for(int i=1;i<=n;i++)cin>>c[i];
	for(int i=1;i<=n;i++){
		mp[b[c[i]]]++;
	}
	ll ans=0;
	for(int i=1;i<=n;i++){
		if(mp[a[i]]!=0)ans+=mp[a[i]];
	}
	cout<<ans;
	
}

H and V

问你选择任意个数行任意个数列,使得剩下的#为k个。

我们可以使用二进制枚举每种情况就可以算出来。

#include <bits/stdc++.h>
int n,m,k;
char a[10][10];
int main() {
    ios::sync_with_stdio(false);cin.tie(0);
  	cin>>n>>m>>k;
  	int sum=0;
  	for(int i=0;i<n;++i){
  		for(int j=0;j<m;++j){
  			cin>>a[i][j];
  			if(a[i][j]=='#') sum++;
  		}
  	}

  	int cnt=0;
  	int ans=0;
  	 for(int i=0;i<(1<<n);++i){
  	 	for(int j=0;j<(1<<m);++j){
  	 		cnt=0;
  	 		for(int r=0;r<n;++r){
  	 			for(int c=0;c<m;++c){
  	 				if( ((i&(1<<r)) || (j&(1<<c)))&& a[r][c]=='#') cnt++;
  	 			} 
  	 		}
  	 		if(cnt==sum-k) ans++;
  	 	}
  	 }

  	 cout<<ans<<endl;

    return 0;
}

Sum of Divisors

思路:预处理,预处理每个数,它的倍数约它是正约数,预处理每个数的正约数的数量。然后加就行

#include <bits/stdc++.h>
using namespace std;

const long long MAXN = 10000001;
long long divisors[MAXN + 1];

void sieve() {
    for (long long i = 1; i <= MAXN; i++) {
        for (long long j = i; j <= MAXN; j += i) {
            divisors[j]++;
        }
    }
}

int main() {
    ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
    long long n;
    cin >> n;

    sieve(); // 预处理每个数的因数个数

    long long sum = 0;
    for (long long i = 1; i <= n; i++) {
        sum += divisors[i] * i;
    }

    cout << sum;
    return 0;
}

Red and Green Apples

思路:思维题,我一开始单独处理红苹果,绿苹果,无色苹果分别对这两个处理。导致一直有点过不了。

我们应该把前x大的红苹果和前y大的绿苹果拿出来放一起成新的苹果,然后拿无色苹果和x+y里面比较,替换就行。

代码

#include <bits/stdc++.h>

using namespace std;
using ll =long long;


int main(){
	ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
	ll x,y,a,b,c;
	cin>>x>>y>>a>>b>>c;
	vector<ll>A(a+1);
	vector<ll>B(b+1);
	vector<ll>C(c+1);
	for(int i=1;i<=a;i++)cin>>A[i];
	for(int i=1;i<=b;i++)cin>>B[i];
	for(int i=1;i<=c;i++)cin>>C[i];
	sort(A.rbegin(),A.rend());
	sort(B.rbegin(),B.rend());
	sort(C.rbegin(),C.rend());
	vector<ll>res(a+b);
	res.resize(x + y);
	merge(A.begin(),A.begin()+x,B.begin(),B.begin()+y,res.begin());
	A.assign(res.begin(),res.end());
	sort(A.begin(),A.end());
	int i = 0, j = 0;
	while (i < c && j < x+y ){
		if (C[i] > A[j]) {
			A[j] = C[i];
			++i;
		}
		++j;
	}
	ll sum=0;
	for(int i=0;i<x+y;i++)sum+=A[i];
	
	cout<<sum;
	
}

Rem of Sum is Num

思路:前缀和取余,记录个数

#include <bits/stdc++.h>

using namespace std;

using ll =long long;

const ll N =10000010;

ll prefix[N];
ll v[N];
map<int,int> mp;
int main(){
	ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
	ll n,k;
	cin>>n>>k;
	
	ll ans=0;
	
	for(int i=1;i<=n;i++)cin>>v[i];
	for(int i=1;i<=n;i++)prefix[i]+=prefix[i-1]+v[i];
	
	for(int i=1;i<=n;i++)prefix[i] = (prefix[i] - i)%k;
	
	int pos = min(n,k-1);
	ll sum = 0;
	
	for(int i= 0 ;i<=pos;i++)
	{
		sum+=mp[prefix[i]];
		mp[prefix[i]] ++;
	}
	
	for(int i=pos+1;i<=n;i++)
	{
		mp[prefix[i-k]] --;
		sum+=mp[prefix[i]];
		mp[prefix[i]]++;
	}
	cout<<sum<<endl;

}

本周总结:

最近状态下滑,在复习学习dfs和bfs的问题,同时回顾了上个星期学的二分等,有了一些收获,但是感觉对一些问题比如二分图,

dp的学习还很浅,需要这个假期认认真真去学。。。加油吧,下个星期把状态找回来,坚持,并且学习新的东西,在学校要有收获。。