Codeforces Round #811 (Div. 3)

Codeforces Round #811 (Div. 3)

A. Everyone Loves to Sleep

原题戳这里

题意+思路: 很简单的模拟,找到与给定时间最接近的时间,算出时间差值就好。(但是注意当时相同,分不同以及转到第二天的情况)

特判多容易出错QAQ


int n,h,m;
void solve()
{
	scanf("%d %d %d",&n,&h,&m);
	int ansh=inf,ansm=inf;
	for(int i=1;i<=n;i++){
		int h1,m1;
		scanf("%d %d",&h1,&m1);
		int t1=0,t2=0;
		if(h1<h){
			if(m!=0){//特判1
				t2=60-m+m1;
				t1=23-h+h1+t2/60;
				t2%=60;
			}
			else {
				t1=24-h+h1;
				t2=m1;
			}
		}
		else if(h==h1){
			if(m1>=m)t2=m1-m;//特判2
			else {
				t2=60-m+m1;
				t1=23-h+h1+t2/60;
				t2%=60;
			}
		}
		else{
			if(m<=m1){//特判3
				t1=h1-h;
				t2=m1-m;
			}
			else{
				t2=60-m+m1;
				t1=h1-1-h+t2/60;
				t2%=60;
			}
		}
		if(t1<ansh)//特判4
			ansh=t1,ansm=t2;
		else if(t1==ansh&&t2<ansm)
			ansm=t2;
	}
	printf("%d %d\n",ansh,ansm);
	return;
}

B. Remove Prefix

原题戳这里

题意与思路: 每次删除最前面的一个数,使得留下来的数互不相同。找到最长的没有重复数字的后缀数组。

int n;
int a[N];
void solve()
{
	int n;
	scanf("%d",&n);
	for(int i=1;i<=n;i++)scanf("%d",&a[i]);
	map<int,int>mp;
	for(int i=n;i>=1;i--){
		if(!mp[a[i]])mp[a[i]]++;
		else {
			printf("%d\n",i);
			return;
		}
	}
	printf("%d\n",0);
	return;
}

C. Minimum Varied Number

原题戳这里

题意与思路: 找到数位和是n的最小的数,那么首先要求数位最少,最后多个数参与则小的尽量放在前面。

int n;

const int N=2e5+10;
int a[N];
void solve()
{
	int n;
	scanf("%d",&n);
	vector<int>v;
	for(int i=9;i>=1;i--){
		if(n>=i){
			n-=i;
			v.push_back(i);
		}
		else break;
	}
	v.push_back(n);
	sort(v.begin(),v.end());
	for(int i=0;i<v.size();i++){
		if(v[i]==0)
			continue;
		else
			printf("%d",v[i]);
	}
	printf("\n");
	return;
}

D. Color with Occurrences

原题戳这里

题意与思路: 给定多个字符串,能否将原字符串染色。将能够给原字符串染色的字符串存下来,因为可能存在字符串aba染色后,后面可能还会有ab,ba也能够将aba染色重复染色的情况,所以要避免。

挺好的模拟,得想清楚,当时没写出来QAQ

string s;
int n;
int length;

struct node{
	int l,r,id;
};

bool check(int start, string t) {//判断目前字符串在原始字符串中能否染色
    int maxn = length - start + 1;
    if (maxn < t.size()) return 0;
    for (int i = start, j = 0; j < (int)t.size(); ++i, ++j) {
        if (t[j] != s[i]) return 0;
    }
    return 1;
}

void solve() {

    int n;
    cin >> s >> n;
    vector<node>v;
    length = s.size();
    s = " " + s;
    for (int i = 1; i <= n; ++i) {
        string t;
        cin >> t;
        int len = t.size();
        for (int j = 1; j  <= length; ++j) {
            if (check(j, t)) v.push_back({j, j + len - 1, i});
        }
    }
    sort(v.begin(), v.end(),[](node a,node b){
    	if(a.l!=b.l)return a.l<b.l;
    	else return a.r<b.r;
    });//排序,尽量让能够染色前面的字符串的在前面
    bool flag = 0;
    int start = 1, end = length;
    vector<PII> ans;
    for (int i = 0; i < v.size(); ++i) {
        int j = i, r = -inf;

        int t = 0;
        while (j < v.size() && v[j].l <= start) {//尽量选择能够染色的最长的字符串
            if (v[j].r > r){
                r = v[j].r;
                t = j;
            }
            j++;
        }
        if (r < start) break;
        start = r+1,i = j-1;
        ans.push_back({v[t].id,v[t].l});
        if(r>= end){
            flag = true;
            break;
        }
    }
    if(flag){
        printf("%d\n",ans.size());
        for(auto it:ans)
        	printf("%d %d\n",it.first,it.second);
    }
    else printf("-1\n");
}

E. Add Modulo 10

原题戳这里

题意与思路: 每次可以对数进行操作,a+=a%10,那么最后能不能使得所有的数字相同。很显然有规律,当数结尾都是0、5时,0结尾最后还是原数,5结尾最后只能等于+5的数,直接判断相邻数是否相等。

结尾:
0:0 0 0 0 0 0 0 0 0......
1:1 2 4 8 6 2 4 8 6......
2:2 4 8 6 2 4 8 6 2......
3:3 6 2 4 8 6 2 4 8......
4:4 8 6 2 4 8 6 2 4......
5:5 0 0 0 0 0 0 0 0......
6:6 2 4 8 6 2 4 8 6......
7:7 4 8 6 2 4 8 6 2......
8:8 6 2 4 8 6 2 4 8......
9:9 8 6 2 4 8 6 2 4......
//观察规律很容易得到两个数将尾数统一之后的差值只能是20的整数倍
//需要注意奇数结尾先要将奇数变成偶数
const int N=2E5+10;
void solve()
{
	int n;
	scanf("%d",&n);
	int a[N];
	int flag1=0,flag2=0;
	for(int i=1;i<=n;i++){
		scanf("%d",&a[i]);
		if(a[i]%10==0||a[i]%10==5)flag1++;
		else flag2++;
		if(a[i]%10==5)a[i]+=5;
	}
	if(flag1&&flag2)puts("NO");
	else if(!flag2){
		for(int i=2;i<=n;i++){
			if(a[i]!=a[i-1]){
				puts("NO");
				return;
			}
		}
		puts("YES");
	}
	else{
		int flag=1;
		for(int i=1;i<n;i++){
			int t=a[i];
			if(a[i+1]%10&1)a[i+1]+=a[i+1]%10;
				while(t%10!=a[i+1]%10)
					t+=t%10;
				if((max(t,a[i+1])-min(t,a[i+1]))%20!=0){
					flag=0;
					break;
				}
		}
		if(flag)puts("YES");
		else puts("NO");
	}
}

总结

继续加油,努力,向前冲!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值