2022牛客寒假算法基础集训营 4(四) 全部题解

本文介绍了多个算法竞赛中的题目及其解题思路,涵盖了字符串处理、线段树、计算几何、模拟、数学优化等多个方面,展示了如何利用R模拟、进制线段树、前缀和等技术解决复杂问题,并提供了详细的代码实现。


比赛链接
题解https://ac.nowcoder.com/discuss/835616?type=101&channel=-1&source_id=0


A R 模拟

题目链接
题意:
给一个包含只包含大写字母的字符串,找有多少个子串包含 k k k R R R 字符且不包含 P P P 字符
在这里插入图片描述
题解:

不包括 P P P 就分段来计算
至少包含 k k k R R R
贡献就等于这个位置 第前 k 个 R R R 位置

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=2e5+5;
int a[N], p[N];
signed main() {
   
   
    int n, k; cin>>n>>k;
    string s; cin>>s;
    s=s+"P";
    int cnt=0;
    a[0]=-1;
	for (int i=0; i<=n; i++) {
   
   
		if(s[i]=='P') a[++cnt]=i;
	}
	int ans=0; 
	for(int j=1; j<=cnt; j++) {
   
    
		int cntt=0;
		p[0]=0;
		for (int i=a[j-1]+1; i<a[j]; i++) {
   
   
			if (s[i]=='R') p[++cntt]=i+1-a[j-1]-1;
			if(cntt>=k) ans+=p[cntt-k+1];
		}
	}
	cout<<ans<<endl;
    return 0;
}

B 进制 线段树

题目链接
题意:
在这里插入图片描述

题解:
所能表示的某进制的最小值的某进制就是该串里的最大的数字+1,不然那个数不可能出现
题目要求单点修改和区间查询
那就是最简单的求最大值和求和的线段树板子
求和的线段树是存了2-10进制棵每一位的数字 * 该位权值
比如10进制树 123存的是1 * 10 * 10 ------- 2*10 -------3
求和出来还要除与多的权值 取[1,2] ,答案等于120/10

这个求和的bug真的找了一万年呜呜呜
在这里插入图片描述

#include<bits/stdc++.h>
#define int long long
#define ll long long
using namespace std;
const int N=1e5+5;
const int M=1e9+7;
int a[N];
int b[13][N];
int n, q;
int p[13][N];
int maxx[4*N];
int sum[13][4*N];
ll ksm(ll a,ll p){
   
   ll res=1;while(p){
   
   if(p&1){
   
   res=res*a%M;}a=a*a%M;p>>=1;}return res;}
void pushup(int id) {
   
   
    maxx[id] = max(maxx[id << 1], maxx[id << 1 | 1]);
}
void build(int id, int l, int r) {
   
   
    if (l == r) {
   
   
        maxx[id] = a[l];
        return;
    }
    int mid = (l + r) >> 1;
    build(id << 1, l, mid);
    build(id << 1 | 1, mid + 1, r);
    pushup(id);
}
void update(int id, int l, int r, int x, int v) {
   
   
    if (l == r) {
   
   
        maxx[id] = v;
        return;
    }
    int mid = (l + r) >> 1;
    if (x <= mid) {
   
   
        update(id << 1, l, mid, x, v);
    } else {
   
   
        update(id << 1 | 1, mid + 1, r, x, v);
    }
    pushup(id);
}
int query(int id, int l, int r, int x, int y) {
   
   
    if(x<=l&&r<=y) {
   
   
        return maxx[id];
    }
    int mid=(l+r)>>1;
    int ans=0;
    if(x<=mid) {
   
   
        ans=max(ans, query(id<<1, l, mid, x, y));
    }
    if(y>mid) {
   
   
        ans=max(ans, query(id<<1|1, mid+1, r, x, y));
    }
    return ans;
}
void pushup1(int id, int jin) {
   
   
    sum[jin][id] = 
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值