比赛链接:Codeforces Round 923 (Div. 3)
D题传送门:D. Find the Different Ones!
题目:
Example
input
5
5
1 1 2 1 1
3
1 5
1 2
1 3
6
30 20 20 10 10 20
5
1 2
2 3
2 4
2 6
3 5
4
5 2 3 4
4
1 2
1 4
2 3
2 4
5
1 4 3 2 4
5
1 5
2 4
3 4
3 5
4 5
5
2 3 1 4 2
7
1 2
1 4
1 5
2 4
2 5
3 5
4 5
output
2 3
-1 -1
1 3
2 1
-1 -1
4 2
4 6
5 3
1 2
1 2
2 3
3 2
1 3
2 4
3 4
5 3
5 4
1 2
4 2
1 3
2 3
3 2
5 4
5 4
分析:
题目要求: 在数组 a[i] 中,在下标l到r中找到不同的 a[i] ,如果存在输出两个下标,否则输出-1
我们可以定义一个数组 p[i] ,用于记录a[i]的”前缀和“,p[i] = p[i-1] + com,定义 com 用于记录 p[i] 每次增加的值(相邻的 a[i] 是否相等),如果 a[i] = a[i-1],则com = 0;如果 a[i] != a[i-1],com = 1。
对于每次询问,我们使用二分来查找不同 a[i] 的下标用 l,r(l < r) 记录。
如果 a[l] = a[r],找到答案;否则当下标为 mid = (l+r+1)/2 时,求 p[l] 与p[mid]的关系。
如果 p[l] = p[mid] ,说明在 l 到 mid 中,a[i] 都相等,答案可能在 mid 到 r,更新 l 的值;
如果 p[l] != p[mid],说明 l 到 mid 中存在不相等的a[i],更新 r 的值。
代码:
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int tt = sc.nextInt();
while(tt-->0) {
int n = sc.nextInt();
int [] a = new int [n+10];
int [] p = new int [n+10];
for(int i = 1;i <= n;i++) {
a[i] = sc.nextInt();
int com = 1;
if(a[i-1]==a[i]) com=0;
p[i]=p[i-1]+com;
}
int q = sc.nextInt();
while(q-->0) {
int l = sc.nextInt();int r = sc.nextInt();
boolean f = false;
while(l < r) {
if(a[r]!=a[l]) {
f = true;break;
}
int mid = (l+r+1)/2;
if(p[l]==p[mid]) l = mid;
else r = mid;
}
if(f) System.out.println(l+" "+r);
else System.out.println(-1+" "+-1);
}
System.out.println();
}
}
}