A 字典序最大的子序列
题目描述
给定字符串s,s只包含小写字母,请求出字典序最大的子序列。
子序列:https://en.wikipedia.org/wiki/Subsequence
字典序:https://en.wikipedia.org/wiki/Lexicographical_order
子序列:https://en.wikipedia.org/wiki/Subsequence
字典序:https://en.wikipedia.org/wiki/Lexicographical_order
输入描述:
一行一个字符串s (1 <= |s| <= 100,000)。
输出描述:
字典序最大的子序列。
示例1
输入
ababba
输出
bbba
示例2
输入
abbcbccacbbcbaaba
输出
cccccbba
最后一个字符一定在,所以从后面找,单调递增的。
1 #include <bits/stdc++.h> 2 using namespace std; 3 const int N = 1e5+10; 4 char str[N], str1[N]; 5 int main() { 6 cin >> str; 7 int ans = 0; 8 char MAX = 'a'; 9 for(int len = strlen(str)-1; len >= 0; len--) { 10 if(str[len] >= MAX) { 11 MAX = str[len]; 12 str1[ans++] = str[len]; 13 } 14 } 15 for(int i = ans-1; i >= 0; i --) { 16 printf("%c",str1[i]); 17 } 18 printf("\n"); 19 return 0; 20 }
C 任意点
题目描述
平面上有若干个点,从每个点出发,你可以往东南西北任意方向走,直到碰到另一个点,然后才可以改变方向。
请问至少需要加多少个点,使得点对之间互相可以到达。
请问至少需要加多少个点,使得点对之间互相可以到达。
输入描述:
第一行一个整数n表示点数( 1 <= n <= 100)。
第二行n行,每行两个整数xi, yi表示坐标( 1 <= xi, yi <= 1000)。
y轴正方向为北,x轴正方形为东。
输出描述:
输出一个整数表示最少需要加的点的数目。
示例1
输入
2 2 1 1 2
输出
1
示例2
输入
2 2 1 4 1
输出
0
并查集问题,当有两个点可以通时就合并,最后看有几个集合,减1就是答案了。
1 #include <bits/stdc++.h> 2 using namespace std; 3 const int N = 110; 4 int fa[N]; 5 struct Nod{ 6 bool visx[N*10], visy[10*N]; 7 Nod() { 8 memset(visx, 0, sizeof(visx)); 9 memset(visy, 0, sizeof(visy)); 10 } 11 }nod[N]; 12 int find(int x) { 13 return fa[x] == x ? x: find(fa[x]); 14 } 15 void unit(int x, int y) { 16 x = find(x), y = find(y); 17 if(x > y) fa[x] = y; 18 else fa[y] = x; 19 } 20 int main() { 21 int n, ans = 0, x, y; 22 for(int i = 0; i <= 100; i ++) fa[i] = i; 23 cin >> n; 24 for(int i = 0; i < n; i ++) { 25 cin >> x >> y; 26 for(int j = 0; j < i; j ++) { 27 if(nod[j].visx[x] || nod[j].visy[y]) unit(i,j); 28 } 29 nod[i].visx[x] = true; 30 nod[i].visy[y] = true; 31 } 32 for(int i = 0; i < n; i ++) { 33 if(i == find(i)) ans++; 34 } 35 cout << ans - 1 << endl; 36 return 0; 37 }
F 选值
题目描述
给定n个数,从中选出三个数,使得最大的那个减最小的那个的值小于等于d,问有多少种选法。
输入描述:
第一行两个整数n,d(1 <= n <= 100,000,1 <= d <= 1000,000,000);
第二行n个整数满足abs(ai) <= 1,000,000,000。数据保证a单调递增。
输出描述:
输出一个整数表示满足条件的选法。
示例1
输入
4 3 1 2 3 4
输出
4
示例2
输入
4 2 -3 -2 -1 0
输出
2
示例3
输入
5 19 1 10 20 30 50
输出
1
题目已经说了单调,就很容易想到二分,这个还真是二分。从第一个值n-2个遍历,找到所以小于等于ai+d的数量cnt,cnt*(cnt-1)/2 就是选择 ai 时有多少种。
1 #include <bits/stdc++.h> 2 #define ll long long 3 using namespace std; 4 const int N = 1e5+10; 5 ll a[N]; 6 int main() { 7 ll n, d; 8 scanf("%lld%lld",&n,&d); 9 for(int i = 0; i < n; i ++) scanf("%lld",&a[i]); 10 a[n] = 1e10; 11 ll ans = 0; 12 for(int i = 0; i < n-2; i ++) { 13 ll tmp = a[i] + d; 14 int index = upper_bound(a,a+n,tmp) - a -1; 15 // cout << index << endl; 16 ll cnt = index - i; 17 if(cnt > 1) { 18 ans += (cnt-1)*cnt/2; 19 } 20 } 21 cout << ans << endl; 22 return 0; 23 }