ICode9

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

贪心题目选做

2022-07-05 15:33:34  阅读:111  来源: 互联网

标签:ch 题目 int 指针 while 选做 && 贪心 getchar


NC18386 字符串

这道题几乎就是双指针的模板题了。

每次移动一下左端点,然后移动右端点知道满足条件

#include<bits/stdc++.h>

using namespace std;

int v[300] = {};

int32_t main() {
    string s;
    cin >> s;
    int l = 0 , r = -1 , len = s.size() , ans = 1e9 , k = 0;
    while( l < len ){
        while( r < len - 1 && k < 26 ) { // 右指针右移
            r++, v[s[r]]++;
            if (v[s[r]] == 1) k++;
        }

        if( k == 26 ) ans = min( ans , r - l + 1 ); // 满足条件

        if( v[s[l]] == 1 ) k --; // 左指针右移
        v[s[l]] -- , l ++;
        }
    cout << ans << endl;
    return 0;
}

NC207040 丢手绢

这道题也可以用双指针来做。但是值得注意的是因为圆的性质,所以圆上两点之间的距离一定是小于等于半径的。所以如果右指针移动后距离大于半径了,右指针的移动就可以结束了。

#include<bits/stdc++.h>

using namespace std;

int read() {
    int x = 0, f = 1, ch = getchar();
    while ((ch < '0' || ch > '9') && ch != '-') ch = getchar();
    if (ch == '-') f = -1, ch = getchar();
    while (ch >= '0' && ch <= '9') x = (x << 3) + (x << 1) + ch - '0', ch = getchar();
    return x * f;
}

const int N = 1e5+5;
int n , a[N] , ans , sum , cnt ;

int32_t main() {
    n = read();
    for( int i = 0 ; i < n ; i ++ )
        a[i] = read() , sum += a[i];
    for( int i = 0 , j = -1 ; i < n ; i ++ )
    {
        while( cnt * 2 < sum ){
            j = ( j +1 ) % n , cnt += a[j];
            ans = max( ans , min( cnt , sum - cnt ) );
        }
        cnt -= a[i];
    }
    cout << ans << endl;
    return 0;
}

luogu P1102 A-B 数对

这道题主要运用了双指针的方法来写,但是需要运用一些 hash 的思想

在 map 中枚举两个指针,一直移动右指针直到r-l>=c然后判断是否相等,相等就更新答案

#include<bits/stdc++.h>
#define int long long
using namespace std;

int read() {
    int x = 0, f = 1, ch = getchar();
    while ((ch < '0' || ch > '9') && ch != '-') ch = getchar();
    if (ch == '-') f = -1, ch = getchar();
    while (ch >= '0' && ch <= '9') x = (x << 3) + (x << 1) + ch - '0', ch = getchar();
    return x * f;
}

const int N = 1e5+5;
int n , c , cnt;
map< int , int > a;

int32_t main() {
    n = read() , c = read();
    for( int i = 1 , x ; i <= n ; i ++ )
        x = read() , a[x] ++;

    for( auto i = a.begin() , j = i ; i != a.end() && j!= a.end() ; i ++ ){
        while( j != a.end() && j->first - i->first < c ) j ++ ;
        if( j->first - i->first == c )
            cnt += i->second * j->second;
    }
    cout << cnt << endl;

    return 0;
}

luogu P1638 逛画展

比较裸的双指针问题,每次维护一下区间内画的种数就好了

#include<bits/stdc++.h>
using namespace std;

int read() {
    int x = 0, f = 1, ch = getchar();
    while ((ch < '0' || ch > '9') && ch != '-') ch = getchar();
    if (ch == '-') f = -1, ch = getchar();
    while (ch >= '0' && ch <= '9') x = (x << 3) + (x << 1) + ch - '0', ch = getchar();
    return x * f;
}

const int N = 1e6+5 , M = 2e3+5;
int n , m , a[N] , cnt , ansl , ansr , ans = 1e9;
int vis[N];

int32_t main() {
    n = read() , m = read();
    for( int i = 1 ; i <= n ; i ++ )
        a[i] = read();
    for( int l = 1 , r = 0 ; l <= n ; l ++ ){

        while( r < n && cnt < m )
            r ++ , vis[ a[r] ] ++ , cnt += (vis[ a[r] ] == 1 );
        if( cnt == m && ans > r - l + 1 )
            ans = r - l + 1 , ansl = l , ansr = r;

        cnt -= ( vis[ a[l ] ] == 1 ) , vis[ a[l] ] --;
    }
    cout << ansl << " " << ansr << endl;
    return 0;
}

luguoP1381 单词背诵

这道题首先要判断那些单词是不用背的,需要背的单词有多少个,然后用双指针维护出最短的区间。

注意如果需要背的有0 个,那么区间也一定是0

#include<bits/stdc++.h>
using namespace std;

const int N = 1e5+5 , M = 1005;
map< string , int > hs;
int n , m , a[N] , ans = 1e9;
int vis[N];
string cur;


int32_t main() {
    cin >> n;
    for( int i = 1 ; i <= n ; i ++ )
    {
        cin >> cur;
        hs[cur] = i;
    }
    cin >> m;
    for( int i = 1 ; i <= m ; i ++ )
    {
        cin >> cur;
        if( hs.find(cur) == hs.end() ) a[i] = -1;
        else a[i] = hs[ cur ] , vis[ a[i] ] = 1;
    }

    int t = 0;
    for( int i = 1 ; i <= n ; i ++ )
        t += vis[i] , vis[i] = 0;
    cout << t << endl;
    if( t == 0 )
        printf("0\n") , exit(0);
    for( int l = 1 , r = 0 , cnt = 0 ; l <= m ; l ++ ){
        while( r < m && cnt < t ){
            r ++ ;
            if( a[r] == -1 ) continue;
            vis[ a[r] ] ++ , cnt += ( vis[a[r]] == 1 );
        }
        if( cnt == t && r - l + 1 < ans )
            ans = r - l + 1 ;

       if( a[l] != -1 ) cnt -= ( vis[ a[l] ] == 1 ) , vis[ a[l] ] --;
    }
    cout << ( ans == 1e9 ? 0 : ans ) << endl;
    return 0;
}

标签:ch,题目,int,指针,while,选做,&&,贪心,getchar
来源: https://www.cnblogs.com/PHarr/p/16446614.html

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

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

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

ICode9版权所有