题目## 题目
题解:
考察点: 思维,数形结合,暴力
易错点:
1. 1. 1.本题中要求的是相交的半圆,如果存在两个半圆,直径分别为 [ l 1 , r 1 ] [l_1,r_1] [l1,r1]和 [ l 2 , r 2 ] [l_2,r_2] [l2,r2],并且满足 l 1 ≤ l 2 , r 2 ≤ r 1 l_1 \leq l_2,r_2 \leq r_1 l1≤l2,r2≤r1,则不属于相交的情况,所以如果按照结束位置排序的方法来贪心并不可行
2. 2. 2.一定注意题目中明确说明在端点处相交不算相交
解法:
这题通过数形结合的方法更容易理解,设两个半圆的端点分别为 [ l 1 , r 1 ] [l_1,r_1] [l1,r1]和 [ l 2 , r 2 ] [l_2,r_2] [l2,r2],则相交时有如下图所示的情况:

在有了上述结论后,题目就变得简单,直接对于半圆 i i i,直接枚举其前面位置的半圆,看和其是否存在交点,复杂度为 O ( n 2 ) O(n^2) O(n2)
#include "bits/stdc++.h"
using namespace std;
const int maxn=1e3+10;
int T,n;
int a[maxn];
struct node{
int l,r;
}p[maxn];
int main()
{
scanf("%d",&T);
while(T--){
scanf("%d",&n);
memset(a,0,sizeof(a));
memset(p,0,sizeof(p));
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
for(int i=2;i<=n;i++){
p[i-1].l=min(a[i-1],a[i]);
p[i-1].r=max(a[i-1],a[i]);
}
--n;
int flag=0;
for(int i=1;i<=n;i++){
for(int j=1;j<i;j++){ if((p[j].l<p[i].r&&p[j].l>p[i].l&&p[j].r>p[i].r)||(p[j].r<p[i].r&&p[j].r>p[i].l&&p[j].l</p[i].r&&p[j].r></i;j++){>
[题目链接](https://www.nowcoder.com/practice/43d22dbc8bef46529e722dc6a5fb1e2d?tpId=182&tqId=354364&sourceUrl=/exam/oj&channelPut=wcsdn&fromPut=wcsdn)
## 解题思路
计算32位整数二进制表示中1的个数,有几种常用方法:
1. **位运算法**:
- 使用 $\text{n} \& \text{1}$ 判断最低位是否为1
- 右移 $\text{n}$,继续判断
- 统计所有为1的位
2. **n & (n-1) 法**:
- 每次操作会消除最右边的1
- 统计操作次数即为1的个数
- 这种方法更高效,因为只需要处理1的个数次
3. **查表法**:
- 预处理所有8位数的1的个数
- 将32位数分成4个8位处理
- 适合处理大量数据
---
## 代码
```c++
#include <iostream>
using namespace std;
class Solution {
public:
// 方法1:位运算统计
int countOnes1(int n) {
int count = 0;
while (n) {
count += n & 1;
n >>= 1;
}
return count;
}
// 方法2:n & (n-1)
int countOnes2(int n) {
int count = 0;
while (n) {
n &= (n - 1);
count++;
}
return count;
}
};
int main() {
int n;
cin >> n;
Solution solution;
cout << solution.countOnes2(n) << endl;
return 0;
}
import java.util.*;
public class Main {
static class Solution {
// 方法1:位运算统计
public int countOnes1(int n) {
int count = 0;
while (n != 0) {
count += n & 1;
n >>>= 1; // 使用无符号右移
}
return count;
}
// 方法2:n & (n-1)
public int countOnes2(int n) {
int count = 0;
while (n != 0) {
n &= (n - 1);
count++;
}
return count;
}
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
Solution solution = new Solution();
System.out.println(solution.countOnes2(n));
}
}
def count_ones_1(n: int) -> int:
"""方法1:位运算统计"""
count = 0
while n:
count += n & 1
n >>= 1
return count
def count_ones_2(n: int) -> int:
"""方法2:n & (n-1)"""
count = 0
while n:
n &= (n - 1)
count += 1
return count
if __name__ == "__main__":
n = int(input())
print(count_ones_2(n))
算法及复杂度
- 算法:位运算
- 时间复杂度:
- 方法1: O ( 32 ) \mathcal{O}(32) O(32) = O ( 1 ) \mathcal{O}(1) O(1)
- 方法2: O ( k ) \mathcal{O}(k) O(k), k k k 为1的个数
- 空间复杂度: O ( 1 ) \mathcal{O}(1) O(1)
732

被折叠的 条评论
为什么被折叠?



