Educational Codeforces Round 166 (Rated for Div. 2)题解(A,B,D)

今天真的巨抽象,第三题没做出来,但是第四题过了,也是准备上小分了,因为nnd不按那个分数,而是按照做题数,直接废了

A. Verify Password

题解:小丑水题一个人,按照ASCII码比较一遍直接过了,最主要要不是一开始卡了3分钟,我感觉能直接在第一题打进前一千

#include<bits/stdc++.h>
using namespace std;
#define int long long
int t;
string s;
signed main()
{
	cin>>t;
	while(t--)
	{
		int flag=1;
	    cin>>s;
		int len=s.size();
		for(int i=1;i<len;i++)
		{
			if(s[i]-'0'<s[i-1]-'0')
			{
				flag=0;
			}
		}
		if(flag==1)
		printf("YES\n");
		else
		printf("NO\n");
	}
	return 0;
}

B. Increase/Decrease/Copy

题解,也不难,主要是去考虑最后一个位置的步数,总共就两种方法,一是先去a数组找到合适的放在最后一个位置,二是在a向b发生变化的时候去放在最后一个位置,找到两个方法的最小的一个步数即可, 别的位置直接一个绝对值秒了

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
#define int long long
int t;
int n;
int a[200005];
int b[200005];
signed main()
{
	cin>>t;
	while(t--)
	{
		int sum=0;//统计总步数
		cin>>n;
		for(int i=1;i<=n;i++)
		cin>>a[i];
		for(int i=1;i<=n+1;i++)
		{
			cin>>b[i];
		}
		for(int i=1;i<=n;i++)
		{
			sum+=labs(b[i]-a[i]);
		}
		int num1=0x3f3f3f3f;//先找差值,再变 
		int flag1=0;;
		int num2=0x3f3f3f3f;//先变,再转移 
		int flag2=0;
		
		//第一中方案 
		for(int i=1;i<=n;i++)
		{
			if(labs(a[i]-b[n+1])<num1)
			{
				num1=labs(a[i]-b[n+1]);
			}
		}
		num1+=1;//第一种方案找到的最小步数
		 
		 
		//第二种方案
		for(int i=1;i<=n;i++)
		{
			int ans=0;
			if(b[n+1]>=max(b[i],a[i])||b[n+1]<=min(a[i],b[i]))
			ans=labs(b[n+1]-b[i])+1;
			else if(b[n+1]<max(b[i],a[i])&&b[n+1]>min(b[i],a[i]))
			ans=1;
			num2=min(ans,num2);
		} 
		
		sum+=min(num1,num2);
		cout<<sum<<"\n";
		
	}
	return 0;
}

D. Invertible Bracket Sequences

题解:这题我们统计序列前个有多少个左括号是剩余的,然后思考(l,r)的选择有何特征:可以发现,若第位之前所剩余的左括号跟第位之前所剩余的左括号数量一样,那么(i+1,j)这个区间就可能被选择,否则一定不会被选择。

然后就可以用前缀和加双指针很轻松的AC了,平常学长给我说的那个stl我也有用,也算是今天用到了吧,set以及pair,平常还是pair用的多一点

因此我们将剩余左括号数量相同的位置放一起,然后考虑其区间能否真的被选中。通过观察可以发现:若之间位置的剩余左括号数量小于等于第位之前所剩余的左括号的两倍,那么这个区间就可以被选中,因此本题转换成区间最值(RMQ问题)。

光这样的朴素算法复杂度是O(n^2logn),这不就直接爆了,怎么能这样做,但是枚举位置时末尾也是非递减的,因而可以用双指针来优化成为O(nlogn)然后就AC了

合法的区间要满足LR的前缀和相等,然后MAX L~R<=2*前缀和

cpp 复制代码
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 200010;
int n, pre[N];
char s[N];
pair<int, int> p[N];
int cnt[N];
set<pair<int, int> > pos[N];

void init()
{
	memset(pre,0,sizeof(pre));
	return ;
}

signed main()
{
    int t;
    cin>>t;
    while(t--)
    {
    	init();
        scanf("%s", s + 1);
        n = strlen(s + 1);
        for(int i = 0; i <= n; i++)
            pos[i].clear(), cnt[i] = 0;
        for(int i = 1; i <= n; i++)
        {
            if(s[i] == '(') pre[i] = pre[i - 1] + 1;
            else pre[i] = pre[i - 1] - 1;
            p[i] = make_pair(pre[i], i);
        }
        sort(p + 1, p + n + 1, greater<pair<int, int> >());
        set<int> ins;
        int ans = 0, R = 0;
        for(int i = 1; i <= n; i++)
        {
            while(R < n && p[R + 1].first > p[i].first * 2)
                ins.insert(p[R + 1].second), R++;
            if(ins.upper_bound(p[i].second) == ins.end())
            {
                ans += pos[p[i].first].size();
            }
            else
            {
                auto it1 = ins.upper_bound(p[i].second);
                auto it2 = pos[p[i].first].lower_bound(make_pair(*it1, 0));
                ans += pos[p[i].first].size();
                if (it2 != pos[p[i].first].end()) ans -= (*it2).second;
            }
            cnt[p[i].first]++;
            pos[p[i].first].insert(make_pair(p[i].second, cnt[p[i].first]));
        }
        printf("%lld\n", ans);
    }
    return 0;
}
相关推荐
CT随2 分钟前
Redis内存碎片详解
java·开发语言
anlog11 分钟前
C#在自定义事件里传递数据
开发语言·c#·自定义事件
奶香臭豆腐24 分钟前
C++ —— 模板类具体化
开发语言·c++·学习
游是水里的游30 分钟前
【算法day19】回溯:分割与子集问题
算法
不想当程序猿_30 分钟前
【蓝桥杯每日一题】分糖果——DFS
c++·算法·蓝桥杯·深度优先
晚夜微雨问海棠呀32 分钟前
长沙景区数据分析项目实现
开发语言·python·信息可视化
graceyun33 分钟前
C语言初阶习题【9】数9的个数
c语言·开发语言
cdut_suye42 分钟前
Linux工具使用指南:从apt管理、gcc编译到makefile构建与gdb调试
java·linux·运维·服务器·c++·人工智能·python
南城花随雪。1 小时前
单片机:实现FFT快速傅里叶变换算法(附带源码)
单片机·嵌入式硬件·算法
dundunmm1 小时前
机器学习之scikit-learn(简称 sklearn)
python·算法·机器学习·scikit-learn·sklearn·分类算法