div3真简单
A - Circle of Students
分析:模拟一下两个方向是否成立就可以了。
#include "bits/stdc++.h"
using namespace std;
int main() {
int q;
cin >> q;
while (q--) {
int n;
cin>>n;
vector<int> v;
v.reserve(n + 1);
int st = -1;
for (int i = 1; i <= n; ++i) {
scanf("%d", &v[i]);
if (v[i] == 1)st = i;
}
int cnt = 1;
bool ok = 1;
for (int i = st; cnt <= n && ok; ++i) {
if (i > n)i = 1;
if (v[i] == cnt){
cnt++;
continue;
}
ok = 0;
}
if (ok) {
puts("YES");
continue;
}
cnt = 1;
ok = 1;
for (int i = st; cnt <= n && ok; --i) {
if (i == 0)i = n;
if (v[i] == cnt){
cnt++;
continue;
}
ok = 0;
cnt++;
}
if (ok) {
puts("YES");
continue;
}
puts("NO");
}
}
B - Equal Rectangles
分析:每个矩形都要面积相等,那么肯定是最长的两根和最短的两根,次长的两根和次短的两根,依次类推,check一下面积是否相等就可以了。
#include "bits/stdc++.h"
using namespace std;
int a[1000];
int main() {
int t;cin>>t;
while(t--){
int n;
cin>>n;
for (int i = 1; i <= 4*n; ++i) {
scanf("%d",&a[i]);
}
sort(a+1,a+1+4*n);
bool ok = 1;
for (int i = 1; i <= 4*n && ok ; i+=2) {
if(a[i] != a[i+1])ok=0;
}
if(!ok){
puts("NO");
continue;
}
int s = 0;
ok = 1;
for (int i = 1,j = 4*n; i <= 2*n && ok; i+=2,j-=2) {
if(s==0)s=a[i]*a[j];
else if(s!=a[i]*a[j])ok = 0;
}
if(ok)puts("YES");
else puts("NO");
}
}
C - Common Divisors
分析:找出gcd然后求一下gcd的因子个数就可以了。
#include "bits/stdc++.h"
using namespace std;
long long a[400004];
int main() {
int n;
cin>>n;
long long g = 0;
for (int i = 1; i <= n; ++i) {
scanf("%lld",&a[i]);
if(g == 0)g = a[i];
else g = __gcd(a[i],g);
}
long long ans = 0;
for (long long i = 1; i*i <= g; ++i) {
if(g % i == 0){
if(i*i!=g)ans += 2;
else ans += 1;
}
}
cout<<ans<<endl;
}
D1 - Remove the Substring (easy version) && D2 - Remove the Substring (hard version)
分析:可以删去的部分肯定是某个子序列中相邻的两个字符之间的部分,并且要求最长。那么直接求一个最靠前的子序列和一个最靠后的子序列,下标分别表示为pre[i]和suf[i],然后枚举一个分割点i,那么肯定存在一个子序列,这个子序列i以前的下标是pre[i],i以后的下标是suf[i+1],遍历求一遍最大值就可以了。
#include "bits/stdc++.h"
using namespace std;
string s, t;
int pre[200004],suf[200004];
int main() {
cin >> s >> t;
int pos = 0;
for (int i = 0; i < s.length(); ++i) {
if (pos < t.length() && s[i] == t[pos]) {
pre[pos]=i;pos++;
}
}
pos = t.size() - 1;
for (int i = s.size() - 1; i >= 0; --i) {
if (pos >=0 && s[i] == t[pos]) {
suf[pos]=i;
pos--;
}
}
int ans = 0;
for (int i = 0; i < t.size() - 1; ++i) {
ans = max(suf[i+1] - pre[i] - 1,ans);
}
ans = max(ans,max((int)s.size() - 1 - pre[t.size()-1],suf[0]));
cout << ans << endl;
}
E - Boxers
分析:排序之后从大到小遍历一遍,按照+1,不变,-1,这样的优先级判断就可以了。
#include "bits/stdc++.h"
using namespace std;
int a[150004];
int main() {
int n ;
cin>>n;
for (int i = 0; i < n; ++i) {
cin>>a[i];
}
int ans = 0;
sort(a,a+n);
int last = 1e9;
for (int i = n-1; i >= 0 ; --i) {
if(a[i] + 1 < last){
ans ++;
last = a[i] + 1;
}
else if(a[i] < last){
ans ++;
last = a[i];
}
else if(a[i] - 1 > 0 && a[i] - 1 < last){
ans ++;
last = a[i] - 1;
}
}
cout<<ans<<endl;
}
F1 - Complete the Projects (easy version)
分析:首先把任务分为两部分,一部分b>0,另一部分b<0。优先把b>0的做完再做b<0的,判断b>0能否做完很easy。
对于b<0的部分,对于每个任务,做完这个任务之后的等级的范围是[a+b,∞],同时做完一个任务,等级就会减小。也就是说,要让每个任务都做完,我们只需要按照a-b的大小,从大开始做就可以了。
#include "bits/stdc++.h"
using namespace std;
int a[104];
int b[104];
struct node {
int a, b;
bool friend operator<(node a, node b) {
if (a.a == b.a)return a.b > b.b;
return a.a < b.a;
}
};
bool cmp(node a, node b) {
return a.a+a.b > b.a+b.b;
}
int main() {
int n, r;
cin >> n >> r;
vector<node> v1, v2;
priority_queue<node> q;
for (int i = 1; i <= n; ++i) {
scanf("%d%d", &a[i], &b[i]);
if (b[i] >= 0) {
v1.push_back({a[i], b[i]});
} else v2.push_back({a[i], b[i]});
}
sort(v1.begin(), v1.end());
sort(v2.begin(), v2.end(), cmp);
int ans = 0;
bool ok = 1;
for (int i = 0; i < v1.size() && ok; ++i) {
if (v1[i].a <= r){
ans ++;
r += v1[i].b;
}
else ok = 0;
}
if(!ok){
puts("NO");
return 0;
}
for (int i = 0; i < v2.size(); ++i) {
if(r >= v2[i].a){
r += v2[i].b;
ans++;
}
else {
puts("NO");
return 0;
}
}
if(r < 0)puts("NO");
else puts("YES");
}
F2 - Complete the Projects (hard version)
分析:同样按照F1一样的处理方法,对b>0的直接判断,b<0的对a+b从小到大排序后再处理。
用DP[i][j]表示选第i个的时候,从等级j开始,的最大值。
由于对a+b从小到大排序,那么在i前面的一定比i后选,所以dp[i][j]=max dp[i-1][j+b]+1。
#include "bits/stdc++.h"
using namespace std;
int a[104];
int b[104];
int dp[104][60004];
struct node {
int a, b;
bool friend operator<(node a, node b) {
if (a.a == b.a)return a.b > b.b;
return a.a < b.a;
}
};
bool cmp(node a, node b) {
return a.a +a.b < b.a + b.b;
}
int main() {
int n, r;
cin >> n >> r;
vector<node> v1, v2;
v2.push_back({0, 0});
for (int i = 1; i <= n; ++i) {
scanf("%d%d", &a[i], &b[i]);
if (b[i] >= 0) {
v1.push_back({a[i], b[i]});
} else v2.push_back({a[i], b[i]});
}
sort(v1.begin(), v1.end());
sort(v2.begin() + 1, v2.end(),cmp);
int ans = 0;
for (int i = 0; i < v1.size(); ++i) {
if (v1[i].a <= r) {
ans++;
r += v1[i].b;
} else break;
}
int maxi = 0;
for (int i = 1; i < v2.size(); ++i) {
for (int j = 0; j <= r; ++j) {
dp[i][j] = dp[i - 1][j];
}
for (int j = r; j >= v2[i].a && j + v2[i].b >= 0; --j) {
dp[i][j] = max(dp[i][j], dp[i - 1][j + v2[i].b] + 1);
maxi = max(maxi, dp[i][j]);
}
}
cout << ans + maxi << endl;
}