2024牛客暑期多校训练营9

 I Interesting Numbers

解析:简单题,但不会用__int128,代码一直写错

#include<bits/stdc++.h>
using namespace std;
/*
ios::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(nullptr);
*/
typedef long long LL;
#define int long long
#define ld long double
#define INT __int128
const LL INF = 0x3f3f3f3f3f3f3f3f;
typedef unsigned long long ULL;
typedef pair<long long, long long> PLL;
typedef pair<int, int> PII;
typedef pair<double, double> PDD;
const int inf = 0x3f3f3f3f;
const LL Mod = 998244353;
const ld eps = 1e-12;
const int N = 1e5 + 10, M = 5e5 + 10;
int n;
string L,R;
INT qpow;
void out(INT u){
    if(u>=10)out(u/10);
    int t=u%10;
    cout<<t;
}
INT find(INT u){
    INT l=0,r=1e18,ret=l;
    while(l<=r){
        INT mid=l+(r-l)/2;
        if(mid*mid<=u){
            ret=mid;
            l=mid+1;
        }
        else{
            r=mid-1;
        }
    }
    return ret;
}
INT solve(string s,int t){
  INT H=0,L=0;
    for(int i=1;i<=s.size();i++){
        if(i<=s.size()/2){
            H=H*10+s[i-1]-'0';
        }
        else{
            L=L*10+s[i-1]-'0';
        }
   }

    qpow=1;
    for(int i=1;i<=n/2;i++){
        qpow*=10;
    }
    if(L<t){
        L=qpow-t;
        if(H>=t)
            H-=t;
    }
    else{
        L-=t;
    }
    int T=qpow;
    qpow=find(qpow);

    INT HH=find(H);
    INT ll=find(L);
    INT ret=0;
    if(qpow*qpow>=T)qpow--;
    if(HH*HH==H){
        ret=(HH)*(qpow+1)+ll+1;
    }
    else{
        ret=(HH+1)*(qpow+1);
    }
    return ret;
}

signed main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);
    cin>>n;
    cin>>L>>R;
    INT retR=solve(R,0);
    INT retL=solve(L,1);
    out(retR-retL);
    return 0;
}

/*



4
2345 5678

58

100000000000000000000000000000000000000000000000000000000 9000000000000000000000000000000000000000000000000000000000


10
1000000000 9000000000

6
100000 999999

2

9 99

2
10 99

*/

B    Break Sequence

 解析:线段树优化dp

很容易看出来本题需要使用dp算法,f[i]:表示钱 i 个元素的划分方案。

直接转移的时间复杂度是O(n*n*m)

优化:由于m很小,因此可以对 S 进行扫描,可以发现对于某个值 x 而言,会是其不合法的区间只有一个,区间左端点在从当前位置往左数第 j+1 个 x 的位置,区间右端点在从当前位置往左数第 j 个 x 的位置-1 的位置,对于不合法的区间,可以用线段树进行维护。
(本题对不合法区间的维护的思想与此D题很像:Codeforces Round 965 (Div. 2)-优快云博客

#include <iostream>
#include <string>
#include <cstring>
#include <cmath>
#include <ctime>
#include <algorithm>
#include <utility>
#include <stack>
#include <queue>
#include <vector>
#include <set>
#include <math.h>
#include <map>
#include <sstream>
#include <deque>
#include <unordered_map>
#include <unordered_set>
#include <bitset>
#include <stdio.h>
#include <tuple>
using namespace std;
/*
ios::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(nullptr);
*/
typedef long long LL;
#define int long long
#define ld long double
//#define INT __int128
const LL INF = 0x3f3f3f3f3f3f3f3f;
typedef unsigned long long ULL;
typedef pair<long long, long long> PLL;
typedef pair<int, int> PII;
typedef pair<double, double> PDD;
const int inf = 0x3f3f3f3f;
const LL mod = 998244353;
const ld eps = 1e-12;
const int N = 2e5 + 10, M = 5e5 + 10;
int n, m;
int A[N], f[N];
vector<int>v[N];
struct TREE {
	int tg;
	int v, sum;
}tr[N<<2];
#define ls u<<1
#define rs u<<1|1
void up(int u) {
	tr[u].v = min(tr[ls].v, tr[rs].v);
	tr[u].sum = 0;
	if (tr[u].v == tr[ls].v)tr[u].sum += tr[ls].sum, tr[u].sum %= mod;
	if (tr[u].v == tr[rs].v)tr[u].sum += tr[rs].sum, tr[u].sum %= mod;
}
void down(int u) {
	if (tr[u].tg) {
		tr[ls].tg += tr[u].tg;
		tr[ls].v += tr[u].tg;
		tr[rs].tg += tr[u].tg;
		tr[rs].v += tr[u].tg;
		tr[u].tg = 0;
	}
}
void add(int l, int r, int u, int ql, int qr, int d) {
	if (ql <= l && r <= qr) {
		tr[u].sum = d;
		return;
	}
	down(u);
	int mid = l + r >> 1;
	if (ql <= mid)add(l, mid, ls, ql, qr, d);
	if (qr > mid)add(mid + 1, r, rs, ql, qr, d);
	up(u);
}
void modify(int l, int r, int u, int ql, int qr, int d) {

	if (ql <= l && r <= qr) {
		tr[u].v += d;
		tr[u].tg += d;
		//cout << "_+++++++++++" << l << " " << r << " " << tr[u].v << endl;
		return;
	}
	down(u);
	int mid = l + r >> 1;
	if (ql <= mid)modify(l, mid, ls, ql, qr, d);
	if (qr > mid)modify(mid + 1, r, rs, ql, qr, d);
	up(u);
}
signed main() {
	ios::sync_with_stdio(false);
	cin.tie(nullptr);
	cout.tie(nullptr);
	cin >> n >> m;
	for (int i = 1; i <= n; i++) {
		cin >> A[i];
	}
	vector<int>s;
	s.reserve(m + 2);
	for (int i = 1; i <= m; i++) {
		int a;
		cin >> a;
		s.push_back(a);
	}
	add(0, n, 1, 0, 0, 1);
	for (int i = 1; i <= n; i++) {
		for (int j : s) {
			if (j < v[A[i]].size()) {
				modify(0, n, 1, v[A[i]][v[A[i]].size() - j - 1], v[A[i]][v[A[i]].size() - j] - 1, -1);
				//cout << "++++++++++++++++++" << v[A[i]][v[A[i]].size() - j - 1] << " " << v[A[i]][v[A[i]].size() - j] - 1 << endl;
			}
			else if (j == v[A[i]].size()) {
				modify(0, n, 1, 0, v[A[i]][v[A[i]].size() - j] - 1, -1);
				//cout << "++++++++++++++++++" << 0 << " " << v[A[i]][v[A[i]].size() - j] - 1 << endl;
			}
		}
		v[A[i]].push_back(i);
		for (int j : s) {
			if (j < v[A[i]].size()) {
				modify(0, n, 1, v[A[i]][v[A[i]].size() - j - 1], v[A[i]][v[A[i]].size() - j] - 1, 1);
				//cout << "___________________" << v[A[i]][v[A[i]].size() - j - 1] << " " << v[A[i]][v[A[i]].size() - j] - 1 << endl;
			}
			else if (j == v[A[i]].size()) {
				modify(0, n, 1, 0, v[A[i]][v[A[i]].size() - j] - 1, 1);
				//cout << "___________________" << 0 << " " << v[A[i]][v[A[i]].size() - j] - 1 << endl;
			}
		}
		f[i] = tr[1].sum;
		//cout << "=========================_" << f[i] << " " << i <<" "<<tr[1].v<< endl;
		add(0, n, 1, i, i, f[i]);
	}
	cout << f[n] << endl;
	return 0;
}

/*
3 1
1 1 1
1


6 1
6 1 2 3 1 3
2

25 2
2 1 1 3 5 1 4 3 3 1 1 1 4 5 3 4 4 3 2 3 5 2 1 3 1
5 4

*/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值