今天真的巨抽象,第三题没做出来,但是第四题过了,也是准备上小分了,因为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;
}