牛客小白月赛27

人懒,几天还没补完所有。。。不太会用这个写文章所以写的有点丑,请见谅
A-巨木之森
B-乐团派对
这题使用DP,将a[i]从小到大排列,dp[i]表示前i个人最多可以组成的乐队数量,我们每次满足第I个人的要求,那么dp[i]=dp[i-a[i]]+1,现在来分析一下其合理性,如果i<a[i],则必然是无法凑一个队的,这时dp[i]=0,当i>=arr[i]时,满足第i人的要求,则剩下i-a[i]人,当然,我们最后一队还可以取a[i]+1,a[i]+2…,但我们dp表示的是i人最多多少个人,最后一队队数始终是1,所以人数应该达到最小,满足最后一队后剩下i-a[i]人,前面我们也经过了相同的处理:恰好满足第i-a[i]人的要求,如此一直往前推,一直到最后出现恰好分配完和还有剩余的情况,如果还有剩余,随便丢进哪一队都可以,所以没有影响。
ac代码

#include<algorithm>
#include<iostream>
#include<cstdio>

using namespace std;

bool cmp(int a, int b) {
    return a > b;
}

const int N = 1e5 + 100;

int arr[N];

int dp[N];

int main() {
    int n;
    cin >> n;
    for (int i = 1; i <= n; i++) cin >> arr[i];
    sort(arr + 1, arr + 1 + n);
    if (arr[n] > n) {
        cout << -1 << endl;
        return 0;
    }
    for (int i = 1; i <= n; i++) {
        if (arr[i] <= i) {
            dp[i] = dp[i - arr[i]] + 1;
        }
    }
    if (dp[n] == 0) cout << -1 << endl;
    else cout << dp[n] << endl;
    return 0;
}

C-光玉小镇
D-巅峰对决
我们注意到任意的两个数都是不同的,所以但区间内的最大值-最小值=r-l,我们可以用线段树维护区间的最大值和最小值
ac代码

#include<iostream>

using namespace std;

const int N = 1e5 + 100;

struct node {
	int max;
	int min;
}tree[N<<2];

int tmax, tmin;

void build(int l, int r, int top) {
	if (l == r) {
		cin >> tree[top].min;
		tree[top].max = tree[top].min ;
		return;
	}
	int mid = (l + r) / 2;
	build(l, mid, top << 1);
	build(mid + 1, r, top << 1 | 1);
	tree[top].max = (tree[top << 1].max > tree[top << 1 | 1].max) ? tree[top << 1].max : tree[top << 1 | 1].max;
	tree[top].min = (tree[top << 1].min < tree[top << 1 | 1].min) ? tree[top << 1].min : tree[top << 1 | 1].min;
}

void change(int l, int r, int top, int x,int y) {
	if (l==x&&r==x) {
		tree[top].max = tree[top].min = y;
		return;
	}
	int mid = (l + r) / 2;
	if (x <= mid) change(l, mid, top << 1, x, y);
	else change(mid + 1, r, top << 1 | 1, x, y);
	tree[top].max = (tree[top << 1].max > tree[top << 1 | 1].max) ? tree[top << 1].max : tree[top << 1 | 1].max;
	tree[top].min = (tree[top << 1].min < tree[top << 1 | 1].min) ? tree[top << 1].min : tree[top << 1 | 1].min;
}

void solve(int l,int r,int top,int L,int R) {
	if (l <= L && R <= r) {
		if (tree[top].max > tmax) tmax = tree[top].max;
		if (tree[top].min < tmin) tmin = tree[top].min;
		return;
	}
	int mid = (L + R) / 2;
	if (l <= mid) solve(l, r, top << 1, L, mid);
	if (r > mid) solve(l, r, top << 1 | 1, mid + 1, R);
}

int main() {
	int n, q;
	cin >> n >> q;
	build(1, n, 1);
	while (q--) {
		int sign,x,y;
		cin >> sign >> x >> y;
		if (sign == 1) {
			change(1, n, 1, x, y);
		}
		else {
			tmax = -1;
			tmin = 0x3f3f3f3f;
			solve(x, y, 1, 1, n);
			if (tmax - tmin == y - x) {
				cout << "YES" << endl;
			}
			else {
				cout << "NO" << endl;
			}
		}
	}
}

E-使徒袭来
注意结果可以是小数,并不是一定时整数,当和一定时三个数相乘最大值的情况:三个数相同,所以反过来想当乘积一定时,和最小的情况下还是三个数相同的情况
ac代码:

#include<iostream>
#include<cstdio>
#include<cmath>

using namespace std;

int main(){
    ios::sync_with_stdio(false);
    double n;
    scanf("%lf",&n);
    double ans = pow(n,1.0/3);
    printf("%.3lf\n",ans*3);
}

F-核弹剑仙
以前做过一道有点类似的题,是一道奶牛排名的题,记不太清楚了,我们将每个物件的强弱关系用有向图表示,如果a比b强,用bitset(一种类似数组的结构,它的每一个元素只能是0或1,每个元素仅用1bit空间)类型的数组ans存结果,第i位是1表示第i件物件强于当前物件,所以ans[b]=ans[b]|ans[a],将直接比b强的和间接比b强的放在了一起。
ac代码

#include<iostream>
#include<bitset>
#include<vector>
#include<algorithm>
#include<queue>

using namespace std;

const int N = 1010;

vector<int> adge[N];

int inadge[N];//入度

queue<int> que;

bitset<N> ans[N];

int n, m;

void solve() {
	for (int i = 1; i <= n; i++) {//拓扑
		if (inadge[i] == 0) {
			que.push(i);
		}
	}
	while (!que.empty()) {
		int u = que.front();
		que.pop();
		for (int i = 0; i < adge[u].size(); i++) {
			int v = adge[u][i];
			inadge[v]--;
			if (inadge[v] == 0) {
				que.push(v);
			}
			ans[v] |= ans[u];
		}
	}
}

int main() {
	cin >> n >> m;
	for (int i = 1; i <= m; i++) {
		int x, y;
		cin >> x >> y;
		adge[x].push_back(y);
		ans[y][x] = 1;
		inadge[y]++;
	}
	solve();
	for (int i = 1; i <= n; i++) {
		cout << ans[i].count() << endl;
	}
}

G-虚空之力
注意这里的字符是不需要连续也不需要有一定的·顺序的,我们直接统计需要的字符的个数,而且显然组成"kinging"的收益比组成"king"的收益比较高,所以我们要尽可能的组成"kinging"

ac代码

#include<cstring>
#include<iostream>
#include<algorithm>

using namespace std;

int main() {
    ios::sync_with_stdio(false);
    int m, ans = 0;
    string str;
    cin >> m >> str;
    int k = 0, i = 0, n = 0, g = 0;
    for (int q = 0; q < m; q++) {
        if (str[q] == 'k') ++k;
        else if (str[q] == 'i') ++i;
        else if (str[q] == 'n') ++n;
        else if (str[q] == 'g') ++g;
    }
    int ti = i / 2, tn = n / 2, tg = g / 2;
    int sign = min(min(k, ti), min(tn, tg));
    ans = sign * 2;
    k -= sign;
    i -= ans;
    n -= ans;
    g -= ans;
    if (k && i && n && g) {
        sign = min(min(k, i), min(n, g));
        ans += sign;
    }
    cout << ans << endl;
}

H-社团游戏
明显的二维前缀和,然而比赛的后半段时间和别人瞎聊去了233,要注意的一点是需要二分

#include<iostream>
#include<bitset>
#include<vector>
#include<algorithm>
#include<queue>

using namespace std;

const int N = 510;

int map[30][N][N];

char str[N][N];

int n, m,k;

bool solve(int i,int j,int l,int r) {
	for (int s = 0; s < 26; s++) {
		int sign = map[s][l][r] - map[s][l][j - 1] - map[s][i - 1][r] + map[s][i - 1][j - 1];
		if (sign > k) return false;
	}
	return true;
}

int main() {
	cin >> n >> m>>k;
	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= m; j++) {
			cin >> str[i][j];
		}
	}
	for (int k = 0; k < 26; k++) {
		for (int i = 1; i <= n; i++) {
			for (int j = 1; j <= m; j++) {
				map[k][i][j] = map[k][i - 1][j] + map[k][i][j - 1] - map[k][i - 1][j - 1]+(k==str[i][j]-'a');
			}
		}
	}
	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= m; j++) {
			int ans = 0;
			for (int l = 1, r = min(n - i, m - j) + 1; l <= r;) {
				int mid = (l + r) / 2;
				if (solve(i, j, i + mid - 1, j + mid - 1)) {
					ans = mid;
					l = mid + 1;
				}
				else {
					r = mid - 1;
				}
			}
			cout << ans <<" ";
		}
		cout << endl;
	}
}

I-名作之壁
当l–r区间是满足条件的,那么l–r(r+1),l–(r+1),…,l–(n)都是满足的,所以我们的目标是对每个l找到这个r,我们维护好l–r的最大值和最小值即可

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<vector>
#include<deque>

using namespace std;

typedef long long ll;

deque<ll> dqmin, dqmax;

const int N = 1e7 + 100;

const ll mod = 1e9;

ll arr[N];

int main() {
	ios::sync_with_stdio(false);
	int n, k, b, c,r = 1, l = 1;
	 scanf("%d %d %lld %d %d",&n,&k,&arr[0],&b,&c);
	ll ans = 0;
	for (; r <= n ;r++ ) {
        arr[r] = (arr[r - 1] * b + c) % mod;
		while (!dqmax.empty() && arr[dqmax.back()] <= arr[r]) dqmax.pop_back();//维护最大值
		dqmax.push_back(r);
		while (!dqmin.empty() && arr[dqmin.back()] >= arr[r]) dqmin.pop_back();//维护最小值
		dqmin.push_back(r);	
		while (!dqmax.empty() && !dqmin.empty() && arr[dqmax.front()] - arr[dqmin.front()] > k) {
			ans += n - r + 1;
			l++;
			if (!dqmax.empty() && dqmax.front() < l) dqmax.pop_front();
			if (!dqmin.empty() && dqmin.front() < l) dqmin.pop_front();
		}
	}
	 printf("%lld\n",ans);
}

J-逃跑路线
ans=x&(21-1)&(22-1)&…&(2n-1),(21-1)&(22-1)&…&(2n-1)=1&11&111&1111&…=1,所以ans=x&1,a[i]范围显然要用到高精,不过太懒了用的java大数

import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.Arrays;
import java.util.Scanner;

public class Main {

    public static void main(String[] args) {

        Scanner scanner = new Scanner(System.in);

        int n = scanner.nextInt();
        
        BigInteger ans = BigInteger.ZERO;
        
        for(int i=1;i<=n;i++){
            BigInteger temp = scanner.nextBigInteger();
            ans=ans.add(temp);
        }
        BigInteger mod = new BigInteger("10");
        
        ans = ans.mod(mod);
        
        int out = ans.intValue();

        System.out.println(out&1);
        
    }

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值