双指针题目选做

1|0NC18386 字符串


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

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

#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; }

2|0NC207040 丢手绢


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

#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; }

3|0luogu 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; }

4|0luogu 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; }

5|0luguoP1381 单词背诵


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

注意如果需要背的有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; }

__EOF__

本文作者PHarr
本文链接https://www.cnblogs.com/PHarr/p/16446614.html
关于博主:前OIer,SMUer
版权声明CC BY-NC 4.0
声援博主:如果这篇文章对您有帮助,不妨给我点个赞
posted @   PHarr  阅读(29)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律
点击右上角即可分享
微信分享提示