ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

一百五十天一千题(DAY 1)

2022-09-14 00:33:24  阅读:215  来源: 互联网

标签:一千 int 题解 cin 一百五十 vector alls sensei DAY


一百五十天一千题 (DAY 1)

目前总题数: 0

目前CF分数: 1325

T1: (ABC 268)C - Chinese Restaurant

// 题解
const int N = 1e6 + 10;
/*
	模拟即可
	但是纯暴力是N^2的 会TLE
	考虑到要把 A[I] 移动到 p=I-1
	需要操作 a[i] - p % N 或者 (a[i]-p+1)%N
	或者 (a[i]-p-1)%N;
	用一个东西储存一下 x次操作的贡献
	输出最大贡献即可
	
	很神奇的一题((
*/

inline void sensei()
{
    int n;
    cin >> n;
    vector<int> a(n+1);
    for(int i=1;i<=n;i++){
        cin >> a[i];
    }
    vector<int> cnt(n+1);
    
    for(int i=1;i<=n;i++){
        int pos = i-1;
        cnt[(((a[i]-pos)%n)+n)%n]++;
        cnt[(((a[i]-pos-1)%n)+n)%n]++;
        cnt[(((a[i]-pos+1)%n)+n)%n]++;
    }
    int ans = -inf_ll;
    for(int i=0;i<=n;i++){
        ans = max(ans,cnt[i]);
    }
    cout << ans << endl;
}

signed main()
{
    sensei();    
    return 0;
}

T2 (ABC 267)C - Index × A(Continuous ver.)

/*
    题目的意思大概就是
    给定一个长度为n的序列a
    以及一个数字m
    要你找到一个长度为m的子序列b
    并且 sigma(bi*i) 最大
*/

/*
题解:
如果暴力写这题,必定会超时
因为时间复杂度为 O(N^2)

但是我们可以通过观察发现一个式子:
例如样例:

10 4
-3 1 -4 1 -5 9 -2 6 -5 3

我们只看前两组m

分别是 
alls = (-3)*1 + (1)*2 + (-4)*3 + (1)*4
alls =          (1)*1 + (-4)*2 + (1)*3 + (-5)*4

这么一看是不是有点做差求和内味了

于是我们得到了一个alls转移的式子:

alls = a[r]*m + (alls - pre[r-1] - pre[l-2]);
其中 r是当前枚举的子序列的右端点,l是左端点

通过这个式子我们可以写出这题
详细见代码

*/


inline void sensei()
{
    int n,m;
    cin >> n >> m;
    vector<int> a(n+1);
    for(int i=1;i<=n;i++){
        cin >> a[i];
    }
    vector<int> pre(n+1);
    for(int i=1;i<=n;i++){
        pre[i] = pre[i-1] + a[i];
    }
    int l,r;
    r = m+1;
    l = 2;
    int alls = 0;
    int ans = -inf_ll;
    for(int i=1;i<=m;i++){
        alls += i*a[i];
    }
    ans = alls;
    while(r <= n){
        alls = a[r]*m+(alls-(pre[r-1]-pre[l-2]));
        ans = max(ans,alls);
        l++;
        r++;
    }
    cout << ans << endl;
}

signed main()
{
    sensei();
    return 0;
}

T4 (ABC 267)D - Index × A(Not Continuous ver.)

/*
	题目含义:
		给你一个长度为n的数组a
		你需要在里面找到一个长度为m的子序列b
		并且 sigma(bi*i) 最大
*/

/*
	题解:
		这题相对于上一题来说,他的数据范围变小了
		M和N都在2000以内
		因此可以考虑一个O(N^2)的做法
		所以我们会考虑能不能dp
		
		定义一个数组 f[][]表示状态
		f[i][j] 表示在前i个数里选j个数组成b的最大值
		状态转移:
			f[i][j] = max(f[i-1][j-1]+a[i]*j,f[i-1][j]);
			
		
*/


inline void sensei()
{
	int n, m;
	cin >> n >> m;
	vector<int> a(n + 1);
	vector<vector<int>> f(2005, vector<int>(2005, -inf_ll));
	for (int i = 1; i <= n; i++) {
		cin >> a[i];
	}
	for (int i = 0; i <= n; i++) {
		f[i][0] = 0;
	}

	for (int i = 1; i <= n; i++) {
		for (int j = 1;j <= m; j++) {
        	if(j <= i )
                f[i][j] = max(f[i - 1][j - 1] + a[i] * j, f[i - 1][j]);
		}
	}
	cout << f[n][m];
}

signed main()
{
	sensei();
	return 0;
}

T5: (CF TON ROUND(DIV1+DIV2)) B. Luke is a Foodie

/*
	题解: 当找到一个区间的最大值和最小值之差大于2*x,cnt++
*/
inline void sensei()
{
    int n,x;
    cin >> n >> x;
    vector<int> a(n+1);
    for(int i=1;i<=n;i++){
        cin >> a[i];
    }
    
    int cnt = 0;
    int alls = 2*x;
    int minn = a[1];
    int maxn = a[1];
    
    for(int i=2;i<=n;i++){
        if(a[i] > maxn){
            maxn = a[i];
        }
        if(a[i] < minn){
            minn = a[i];
        }
        if(maxn - minn > alls) {
            cnt ++;
            minn = a[i];
            maxn = a[i];
        }
    }
    cout << cnt << endl;
}

signed main()
{
    int t;
    cin >> t;
    while(t --){
        sensei();
    }
    return 0;
}

T6 (CF ROUND 795 DIV.2)C. Sum of Substrings

/*
	题目描述:
		题目的大概意思就是
		给你一个只包含0和1的字符串s
		定义f(s) 为这个字符串每两个连续字符代表的十进制的和
		现在你有k次操作去换任意两个相邻字符
		输出f(s)可能的最小值
*/


/*
	题解: 
		贪心即可
		通过观察我们发现
		字符串里面除了第一个字符和最后一个字符出现了'1'  其他地方出现了1 必定对f(s)贡献了11
		而如果我们把某个不是在最后的字符移到了最后,那么 f(s) -= 10
		如果我们把某个不是第一的字符移动到了第一那么f(s) -= 1
		因此我们需要贪心,先考虑能不能移到最后,再考虑能不能移到第一
		注意如果字符串本身全为0那么直接输出0即可

*/



inline void sensei()
{
    int n,k;
    cin >> n >> k;
    int cnt = 0;
    string s = "";
    cin >> s;
    s = " " + s;
    for(int i=1;i<=n;i++){
        if(s[i] == '1'){
            cnt++;
        }
    }
    if(cnt == 0){
        cout << 0 << endl;
        return ;
    }
    int ans = 11*cnt;
    int st,ed;
    st = ed = 0;
    for(int i=1;i<=n;i++){
        if(s[i] == '1'){
            st = i;
            break;
        }
    }

//   debug(s.size());
    for(int i=n;i>=1;i--){
        if(s[i] == '1'){
            ed = i;
            break;
        }
    }
    
    if(st!=ed and st-1+n-ed<=k){
        ans -= 11;
    }else if(k>=n-ed){
        ans -= 10;
    }else if(k>=st-1){
        ans -= 1;
    }
    cout << ans << endl;
    
}

signed main()
{
    fuckios
    int t;
    cin >> t;
    while(t --){
        sensei();
    }
    return 0;
}


快1点了。。。写不动了。。。休息一下。。明天继续

标签:一千,int,题解,cin,一百五十,vector,alls,sensei,DAY
来源: https://www.cnblogs.com/BeB0p/p/16691515.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有