ABC364
A
link
循环判断,除了最后两个点以外,有连续\(2\)个甜的就不能吃完。
点击查看代码
#include<bits/stdc++.h>
using namespace std;
int n;
string s[105];
signed main(){
cin >> n;
for(int i = 1;i <= n;++ i){
cin >> s[i];
if(s[i] == "sweet"&&s[i] == s[i-1]&&i < n){
cout << "No";
return 0;
}
}
cout << "Yes";
return 0;
}
B
link
这个题ABC好像出过一次
循环走就可以了。
点击查看代码
#include<bits/stdc++.h>
using namespace std;
int h,w;
int sx,sy;
char s[55][55];
signed main(){
cin >> h >> w >> sx >> sy;
for(int i = 1;i <= h;++ i){
for(int j = 1;j <= w;++ j){
cin >> s[i][j];
}
}
string ch;
cin >> ch;
for(int i = 0;i < ch.size();++ i){
int xx = sx,yy = sy;
if(ch[i] == 'U') xx--;
if(ch[i] == 'D') xx++;
if(ch[i] == 'L') yy--;
if(ch[i] == 'R') yy++;
if(xx > 0&&xx <= h&&yy > 0
&&yy <= w&&s[xx][yy] == '.'){
sx = xx,sy = yy;
}
}
cout << sx << " " << sy;
return 0;
}
C
link
吃多少菜是由最先结束的一种味道决定的,那么我们看每种味道最少吃几盘,取最小值即可。这里一个如果比另一个小,那么按照它小的方式排列,另一个无论如何也不会比它先结束,所以每一个单独考虑即可。
点击查看代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
int n,x,y;
int a[200005],b[200005];
int qzh[200005];
int ans;
bool cmp(int x,int y){
return x>y;
}
signed main(){
cin >> n >> x >> y;
for(int i = 1;i <= n;++ i)
cin >> a[i];
for(int i = 1;i <= n;++ i)
cin >> b[i];
sort(a+1,a+1+n,cmp);sort(b+1,b+1+n,cmp);
ans = n;
for(int i = 1;i <= n;++ i){
qzh[i] = qzh[i-1]+a[i];
if(qzh[i] > x){
ans = i;
break;
}
}
for(int i = 1;i <= n;++ i){
qzh[i] = qzh[i-1]+b[i];
if(qzh[i] > y){
ans = min(ans,i);
break;
}
}
cout << ans;
return 0;
}
D
link
考虑二分答案,对于一个答案\(k\),找\(b_i-k\)到\(b_i+k\)范围内\(a_i\)的个数。想找这个可以将\(a\)排序,找第一个\(\ge b_i-k\)的数为\(L\)和第一个\(> b_i+k\)的数为\(R\),那么\(b_i-k\)到\(b_i+k\)范围内\(a_i\)的个数就是\(L\)到\(R-1\)的个数,用\(R-L\)即可。
点击查看代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
int n,q;
int a[100005];
int check(int x,int b){
int l = b-x,r = b+x;
int ll = lower_bound(a+1,a+1+n,l)-a-1;
int rr = upper_bound(a+1,a+1+n,r)-a-1-1;
return rr-ll+1;
}
signed main(){
cin >> n >> q;
for(int i = 1;i <= n;++ i)
cin >> a[i];
sort(a+1,a+1+n);
for(int i = 1;i <= q;++ i){
int b,k;
cin >> b >> k;
int l = 0,r = 1e16,md;
while(l < r){
md = (l+r)/2;
int t = check(md,b);
if(t < k) l = md+1;
else r = md;
}
cout << r << endl;
}
return 0;
}
E
link
考虑\(dp_{i,j,k}\)代表考虑了前\(i\)个菜,甜度为\(j\),咸度为\(k\)的最多菜数。空间存不下,考虑交换\(dp\)状态与答案。
考虑\(dp_{i,j,k}\)代表考虑了前\(i\)个菜,甜度为\(j\),选了\(k\)个菜的最小咸度。
考虑转移。
如果不选\(i\),\(dp_{i-1,j,k} \to dp_{i,j,k}\)。
如果符合条件(\(j+a_i \le x\),\(dp_{i-1,j,k}+b_i \le y\)),选\(i\),\(dp_{i-1,j,k}+b_i \to dp_{i,j+a_i,k+1}\)。
注意最后答案要加\(1\),因为最后符合要求的还可以再吃一个才不符合要求。
点击查看代码
#include<bits/stdc++.h>
using namespace std;
int n,x,sx,y;
int a[85],b[85];
int dp[85][20005][85];
signed main(){
cin >> n >> x >> y;
for(int i = 1;i <= n;++ i){
cin >> a[i] >> b[i];
sx += a[i];
}
memset(dp,0x3f,sizeof(dp));
dp[0][0][0] = 0;
for(int i = 1;i <= n;++ i){
for(int j = 0;j <= x;++ j){
for(int k = 0;k < i;++ k){
dp[i][j][k] =
min(dp[i][j][k],dp[i-1][j][k]);
if(j+a[i] <= x&&dp[i-1][j][k]+b[i] <= y){
dp[i][j+a[i]][k+1] =
min(dp[i][j+a[i]][k+1],
dp[i-1][j][k]+b[i]);
}
}
}
}
for(int k = n;k >= 0;-- k){
for(int j = 0;j <= x;++ j){
if(dp[n][j][k] <= y){
cout << min(n,k+1);
return 0;
}
}
}
return 0;
}
F
link
最小生成树算法:\(Kruskal\)(边按照边权排序,加入)。
这个题肯定就是把所有的连边(\(n+i\)到\(l_i\)~\(r_i\)连长为\(c_i\)的边)按长短排序。
首先,要把询问转换,转换为\(n+i\)向\(l_i\)连边,\(l_i\)向\(l_i+1\),\(l_i+1\)向\(l_i+2\),\(l_i+2\)向\(l_i+3\)……\(r_i-1\)向\(r_i\)连边。
每一次一个询问,看看\(l_i\)到\(r_i\)中有哪些位置还没有和下一个位置连边,连上,还要让\(n+i\)向\(l_i\)连边。
正确性(胡诌):因为当前连的这些边是这一个及以后的所有询问中最短的,如果这一个不连,让后面的连,就不优了。
因为后面\(Q\)个点,每一个都向前面\(n\)个连了,所以只要判断前\(n\)个是否联通即可。
优化:用\(set\)存哪些点没有与自己后一个点联通,用二分找大于\(l_i\)的第一个没连的点在哪即可,找完继续往下,连一个删一个,直到到了\(r_i\)。最后判断\(wet\)是否为空。
点击查看代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
int n,q;
struct nd{
int l,r,c;
}a[200005];
set<int> se;
bool cmp(nd x,nd y){
return x.c < y.c;
}
int ans;
signed main(){
cin >> n >> q;
for(int i = 1;i <= q;++ i)
cin >> a[i].l >> a[i].r >> a[i].c;
sort(a+1,a+1+q,cmp);
for(int i = 1;i < n;++ i) se.insert(i);
for(int i = 1;i <= q;++ i){
int l = a[i].l,r = a[i].r;
ans += a[i].c;
set<int>::iterator ll = se.lower_bound(l);
while(ll != se.end()&&*ll+1 <= r)
ans += a[i].c,ll = se.erase(ll);
}
if(se.empty()) cout << ans;
else cout << -1;
return 0;
}