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;
	
}
posted @ 2024-07-29 14:01  校牌杀手  阅读(18)  评论(0编辑  收藏  举报