第15周12.9~12.15

codeforces 859 div4

A

题目

签到题,没有算法,纯if判断然后输出

代码

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

int t,a,b,c;

int main(void){
	ios::sync_with_stdio(false);
	cin.tie(0);cout.tie(0);
	cin >> t;
	for(int i=0;i<t;i++){
		cin >> a >> b >> c;
		if(a+b == c) cout << "+" <<'\n';
		else cout << "-" <<'\n';
	}
	return 0;
}

B

题目

此题贪心,题目简述就是偶数之和大于级数之和就行,难度也是签到的难度

代码

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

int ou=0,ji=0,a,t,n;
int main(void){
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    cin >> t;
    for(int i=0;i<t;i++){
        cin >>n;
        for(int j=0;j<n;j++){
            cin >>a;
            if(a%2==0) ou +=a;
            else ji += a;
        }
        if(ou>ji) cout<<"YES"<<'\n';
        else cout << "No"<<'\n';
        ji=0;ou=0;
    }
    return 0;
}

C

题目

模拟题,字符串处理。此题题意是给你一串字符串,你可以把同种的所有字母都用1或0来代替,问你能不能形成像0101010这种1和0交替出现的形式。用Hash数组来记录字符串中某个字母是否已经被替换,然后判断就行

代码

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

string s;
char cha;
int t,n,Hash[101][2001],pd;

int main(void){
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    cin >>t;
    for(int i=0;i<t;i++){
        cin >> n;cin>>s;
        fill_n(&Hash[0][0],101*2001,-1);
        for(int j=0;j<n;j++){
            if(Hash[t][j] != -1) continue;
            if(j!=n-1 && s[j]==s[j+1]){
                pd=1;break;
            }
            else{
                cha =s[j];
                Hash[t][j]=j%2;
                s[j]='0';
                auto it =s.find(cha);
                while(it != string::npos){
                    Hash[t][it]=j%2;
                    s[it]='0';
                    it = s.find(cha);
                }
            }
        }
        for(int j=0;j<n-1;j++){
            if(Hash[t][j] == Hash[t][j+1]){
                pd=1;break;
            }
        }
        if(pd==0) cout << "YES" <<endl;
        else cout << "NO" << endl;
        pd=0;
    }
    return 0;
}

D

题目

此题题意为给你一个整数数组,把其中a[left]到a[right]都替换为k,问你数组元素之和是否为奇数。我第一遍直接暴力速度解决,结果TLE,发现n和q数据太大了,明显不是让我暴力的。因此改用前缀和解决

代码

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

long long t,n,q,l,r,k,a[200001],cache,sum=0;

int main(void){
	ios::sync_with_stdio(false);
	cin.tie(0);cout.tie(0);
	cin >> t;
	for(int i=0;i<t;i++){
		cin >> n >> q;
		for(int j=0;j<n;j++){
			cin >> cache;
			a[j] = cache;
		}
		for(int j=1;j<n;j++) a[j]+=a[j-1];
		for(int j=0;j<q;j++){
			cin >> 	l >> r >> k;
			if(l>1) sum = a[l-2] + a[n-1]-a[r-1] + (r-l+1)*k;
			else	sum = a[n-1]-a[r-1] + (r-l+1)*k;
			if(sum %2 ==1) cout << "YES" <<'\n';
			else cout << "NO" << '\n';
			sum=0;
		}
	}	
	return 0;
}

E

题目

题干非常长,快有我长了,有点像猜数字的升级版,主要用二分来做

代码

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

int t,n,a[200001],ai,weight=0,weight_in,special,inter,l,r,left=1;

int main(void){
	ios::sync_with_stdio(false);
	cin.tie(0);cout.tie(0);
	cin >> t;
	while(t--){
		cin>>n;
		for(int i=0;i<n;i++){
			cin>>ai;
			a[i]=ai;
		}
		l=1;r=(l+n)/2;weight=0;
		while(1){
			cout<<"?"<<' '<<r-l+1<<' ';
			for(int i=l;i<=r;i++){
				cout<<i<<' ';
				weight+=a[i-1];
			}cout<<endl;
			cin >> weight_in;
			if(weight!=weight_in && r==l ){
				special=l;break;
			}
			if(weight == weight_in) {
				if(l+1==n){
					special=n;break;
				}
				if(r+1<=n) l=r+1;
				else l=r;
				r=(l+n)/2;
				
			}else{
				n=r;
				r=(l+r)/2;
			}
			weight=0;
		}
		cout<<"!"<<' '<<special<<endl;
	}
	return 0;
}

F

题目

这道是这套里最难的题,主要是dfs,一个小球沿着斜线一直跑,碰到墙就转向,碰到墙角就反弹,问你能不能经过某一点。这题的行和列最大都为25000,如果直接room[25000][25000],那么25000250004/1024/1024/1024=2.3GB 会爆栈,改用单独的行和列变量来判断。

初始思路:用dfs双头搜,两次搜索都是碰到墙角就结束,因为两个墙角构成一个死循环,同时判断不撞墙角的死循环的特殊情况,构成四边形死循环也结束。这个思路没有全部AC,从下午调到第二天下午,恼火,然后换了个思路。

AC思路:一个格子有四个方向,一共有nm个格子,所以小球至多走nm*4步,如果超过这个数必然是死循环,结束。

代码

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

int pd = 0, times = 0, room, t, n, m, i1, j_1, i2, j2;
string d;
struct zb {
    int x; int y;
    bool operator==(const zb& other) const {
        return x == other.x && y == other.y;
    }
}Next;
map <string, zb> direction;
#define checkx (Next.x>0 && Next.x<=n) 
#define checky (Next.y>0 && Next.y<=m) 
#define qiangjiao (Next.x<1 && Next.y<1 || Next.x<1 && Next.y>m || Next.x>n && Next.y<1 || Next.x>n && Next.y>m)
void dfs(int dx, int dy, string& d, int& times) {
    if (dx == i2 && dy == j2) {
        pd = 1; return;
    }
    Next.x = dx + direction[d].x;
    Next.y = dy + direction[d].y;
    if (times>room) return;
    if (qiangjiao) {
        times++;
        if (d == "UL") { d = "DR"; Next.x = dx; Next.y = dy; }
        else if (d == "UR") { d = "DL"; Next.x = dx; Next.y = dy; }
        else if (d == "DR") { d = "UL"; Next.x = dx; Next.y = dy; }
        else if (d == "DL") { d = "UR"; Next.x = dx; Next.y = dy; }
    }
    else if (Next.x < 1 && checky) {
        times++;
        if (d == "UL") {
            d = "DL"; Next.x = dx; Next.y = dy;
        }
        if (d == "UR") {
            d = "DR"; Next.x = dx; Next.y = dy;
        }
    }
    else if (Next.x > n && checky) {
        times++;
        if (d == "DR") {
            d = "UR"; Next.x = dx; Next.y = dy;
        }
        if (d == "DL") {
            d = "UL"; Next.x = dx; Next.y = dy;
        }
    }
    else if (checkx && Next.y < 1) {
        times++;
        if (d == "UL") {
            d = "UR"; Next.x = dx; Next.y = dy;
        }
        if (d == "DL") {
            d = "DR"; Next.x = dx; Next.y = dy;
        }
    }
    else if (checkx && Next.y > m) {
        times++;
        if (d == "UR") {
            d = "UL"; Next.x = dx; Next.y = dy;
        }
        if (d == "DR") {
            d = "DL"; Next.x = dx; Next.y = dy;
        }
    }
    dfs(Next.x, Next.y, d, times);
}
int main(void) {
    ios::sync_with_stdio(false);
    cin.tie(0); cout.tie(0);
    direction["UL"] = { -1,-1 };
    direction["UR"] = { -1,1 };
    direction["DR"] = { 1,1 };
    direction["DL"] = { 1,-1 };
    cin >> t;
    while (t--) {
        cin >> n >> m >> i1 >> j_1 >> i2 >> j2 >> d;
        room = n * m * 4;
        dfs(i1, j_1, d,times);
        if (pd) cout << times << '\n';
        else cout << -1 << '\n';
        times = 0; pd = 0;
    }
    return 0;
}

codeforces 950 div3

A

题目

难度比较低,字符串处理

代码

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

string zimu[7]={"A","B","C","D","E","F","G"},inp,cha;
int t,n,m,haxi[51],sum=0;

int main(void){
	ios::sync_with_stdio(false);
	cin.tie(0);cout.tie(0);
	cin >> t;
	while(t--){
		cin >> n >> m >> inp;
		while(m--){
			for(int i=0;i<7;i++){
				cha=zimu[i];
				int it = inp.find(cha);
				if(it == -1) sum++;
				else inp[it]='0';
			}
		}
		cout<<sum<<'\n';
		sum=0;inp.clear();
	}	
	return 0;
}

B

题目

这题考排序,不难,就是特判有点多

代码

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

int t,n,f,k,fav,cache;
vector <int> a;
int main(void){
	ios::sync_with_stdio(false);
	cin.tie(0);cout.tie(0);
	cin >> t;
	while(t--){
		cin >> n >> f >> k;
		for(int i=0;i<n;i++){
			cin >> cache;
			a.push_back(cache);
		}
		fav = a[f-1];
		sort(a.begin(),a.end(),greater<int>());
		if(a[k-1]<fav) cout << "YES" <<'\n';
		else if(a[k-1]>fav) cout << "NO" <<'\n';
		else if(n==1) cout << "YES" <<'\n';
		else if(k<n && a[k]==fav) cout << "MAYBE" <<'\n';
		else cout << "YES" <<'\n';
		a.clear();
	}	
	return 0;
}

C

题目

(这道题居然有156个test!)

题意大概是给你一个初始数组a,和现在的数组b,问你在m次变换(把a[c]赋值为d)后能否变成数组b。

map的搜索非常高效(这道题很坑,不用map几乎必定TLE)

1.如果d的最后一个不在b里,NO

2.如果b[d]==0,NO

否则YES

代码

#include <bits/stdc++.h>
using namespace std;
 
int t, n, cache, m;
vector <int> a,diff;
map <int,int> b,d;

void noTLE(){
	cin >> n;
	for (int i = 0; i < n; i++) {
		cin >> cache;
		a.push_back(cache);
	}
	for (int i = 0; i < n; i++) {
		cin >> cache;
		b[cache]++;
		if(a[i] != cache) diff.push_back(cache);
	}
	cin >> m;
	for (int i = 0; i < m; i++) {
		cin >> cache;
		d[cache]++;
	}
	if(b[cache]==0){
		cout << "NO" <<'\n';
		return;
	}
	for(auto i : diff){
		if(d[i]==0){
			cout << "NO" <<'\n';
			return;
		}
		d[i]--;
	}
	cout << "YES" <<'\n';
	return;
}

int main(void) {
	ios::sync_with_stdio(false);
	cin.tie(0); cout.tie(0);
	cin >> t;
	while (t--) {
	noTLE();
	diff.clear(); a.clear(); b.clear();d.clear();
	}
	return 0;
}

D

题目

这道题挺有难度,为了做这题我花了4小时恶补盲点

用欧几里得算法求出相邻数之间的最大公约数并记录到数组b里,然后用sec1和sec2两个子区间来判断切割a[i]后是否满足条件。还要首尾特判(真挺复杂的)

代码

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

int t,n,cache,a[200001],b[200001];
int gcd(int a,int b){
	return b==0 ? a:gcd(b,a%b);
}
void solve(){
	int sec1[200001],sec2[200001];b[n]=99999999;
	for(int i=1;i<n;i++) b[i]=gcd(a[i],a[i+1]);
	sec1[0]=sec2[n-1]=sec2[n]=1;
	for(int i=1;i<n;i++) 	sec1[i] = sec1[i-1] && b[i-1] <= b[i];
	for(int i=n-2;i>0;i--)  sec2[i] = sec2[i+1] && b[i] <= b[i+1];
	int ans = sec1[n-2] | sec2[2];
	for(int i=2;i<n;i++){
		int k = gcd(a[i-1],a[i+1]);
		ans |= sec1[i-2] && sec2[i+1] && k>=b[i-2] && k<=b[i+1];
	}
	cout << (ans ? "YES\n" : "NO\n");
}
int main(void){
	ios::sync_with_stdio(false);
	cin.tie(0);cout.tie(0);
	cin >> t;
	while(t--){
		cin >> n;
		for(int i=1;i<=n;i++){
			cin>>cache;
			a[i]=cache;
		}
		solve();
	}	
	return 0;
}

codeforces 871 div4

A

题目

字符串逐个字符比较,签到

代码

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

int t,diff=0;
string cf="codeforces",inp;
int main(void){
	ios::sync_with_stdio(false);
	cin.tie(0);cout.tie(0);
	cin >> t;
	while(t--){
		cin >> inp;
		for(int i=0;i<10;i++){
			if(cf[i]!=inp[i]) diff++;
		}
		cout << diff << '\n';
		diff=0;
	}
	return 0;
}

B

题目

求最长含0区间。本来第一思路是双指针的,结果写的时候发现还有更简单的方法,就按更简单的写了。但是双指针我没怎么练过,所以又写了一份双指针的代码。题不难,耗费的时间很少

两种方法的时间复杂度都是O(n),OJ上显示的用时也都是61ms

代码

easy

#include <bits/stdc++.h>
using namespace std;
int t,n,sum=0,sec=0,cache;
int main(void){
	ios::sync_with_stdio(false);
	cin.tie(0);cout.tie(0);
	cin >> t;
	while(t--){
		cin >> n;
		for(int i=0;i<n;i++){
			cin >> cache;
			if(cache==0) {
				sec++;
				sum=max(sum,sec);
			}
			else{
				sum=max(sum,sec);
				sec=0;
			}
		}
		cout << sum << '\n';
		sum=sec=0;
	}
	return 0;
}

two pointers

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

int t,n,cache,a[101],sum=0;
int main(void){
	ios::sync_with_stdio(false);
	cin.tie(0);cout.tie(0);
	cin >> t;
	while(t--){
		cin >> n;
		for(int i=0;i<n;i++){
			cin >> cache;
			a[i]=cache+1;
		}
		if(n==1){
			if(a[0]==1){
				cout << 1 << '\n';
				continue;
			}
			else{
				cout << 0 << '\n';
				continue;
			}
		}
		for(int l=0,r=0;l<n && r<n;){
			if(a[l]==1 && a[r]==1){
				sum = max(sum,r-l+1);
				r++;
			}
			else{
				l=r+1;r=l;
			}
		}
		cout << sum <<'\n';
		sum=0;
	}
	return 0;
}

C

题目

输入的时候就处理,m01、m10、m11存放最小值,然后判断比较。这里需要注意m01、m10、m11初始化取的最大值不能为2e5+1,应为4e5+1(因为m01+m10的最值和可能为4e5,我搁这掉坑里了)

代码

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

int t,n,m01=400001,m10=400001,m11=400001,ca,cm,book;

int main(void){
	ios::sync_with_stdio(false);
	cin.tie(0);cout.tie(0);
	cin >> t;
	while(t--){
		cin >> n;
		while(n--){
			cin >> cm >> book;
			if(book == 10) m10 = min(m10,cm);
			else if(book == 01) m01 = min(m01,cm);
			else if(book == 11) m11 = min(m11,cm);
			}
			if(m11==400001 && (m01==400001 || m10==400001)) cout << -1 << '\n';
			else cout << min(m11,m10+m01) << '\n';
			m01=400001,m10=400001,m11=400001;
	}
	return 0;
}

D

题目

给你一个数n,问你能不能把n拆分后出现数m,拆分的规则是拆成两个数后,一个数是另一个数的两倍。这题DFS搜,有个n==m的特判

代码

#include <bits/stdc++.h>
using namespace std;
int t,n,m,cache;
int dfs(int x){
	if(x%3 != 0) return 0;
	else{
		int x1 = x/3, x2 = x-x1;
		if(x1==m || x2==m) return 1;
		else{
			int k =(dfs(x1));
			if(!k) k = dfs(x2);
			return k;
		}
	}
}
int main(void){
	ios::sync_with_stdio(false);
	cin.tie(0);cout.tie(0);
	cin >> t;
	while(t--){
		cin >> n >> m;
		cout << ((dfs(n) || n==m ) ? "YES\n" : "NO\n");
	}
	return 0;
}

E

题目

二维格子里面,0表示陆地,非零表示湖泊,数字代表湖泊的深度。问相连的湖泊中最深的湖有多深。

BFS搜,用room[][]来判断路是否走过,走过的就不走

代码

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

int room[1002][1002]={0},earth[1002][1002],t,n,m,cache;
int explore[][2]={1,0,-1,0,0,1,0,-1};
struct wei{
	int x,y;
};
queue<wei> q;
#define check (next.x>=0 && next.x<n && next.y>=0 && next.y<m && earth[next.x][next.y]!=0 && room[next.x][next.y]==0)

int bfs(int dx,int dy){
	wei next,start;
	start.x=dx;start.y=dy;int sum=0;
	q.push(start);room[dx][dy]=1;
	while(!q.empty()){
		start = q.front();
		q.pop();
		sum += earth[start.x][start.y];
		for(int i=0;i<4;i++){
			next.x=start.x+explore[i][0];next.y=start.y+explore[i][1];
			if(check){
				room[next.x][next.y]=1;
				q.push(next);
			}
		}
	}
	return sum;
}
int main(void){
	ios::sync_with_stdio(false);
	cin.tie(0);cout.tie(0);
	cin >> t;
	while(t--){
		cin >> n >> m;
		for(int i=0;i<n;i++){
			for(int j=0;j<m;j++){
				cin >> cache;
				earth[i][j]=cache;
				room[i][j]=0;
			}
		}
		int sum=0;
		for(int i=0;i<n;i++)
			for(int j=0;j<m;j++)
				if(earth[i][j] && room[i][j]==0)
					sum=max(sum,bfs(i,j));
		cout << sum << '\n';
	}	
	return 0;
}
posted @ 2025-06-14 11:25  HLAIA  阅读(12)  评论(0)    收藏  举报