小明有一个花园,花园里面一共有m朵花,对于每一朵花,都是不一样的,小明用1~m中的一个整数表示每一朵花。
他很喜欢去看这些花,有一天他看了n次,并将n次他看花的种类是什么按照时间顺序记录下来。
记录用a[i]表示,表示第i次他看了a[i]这朵花。
小红很好奇,她有Q个问题,问[l,r]的时间内,小明一共看了多少朵不同的花儿,小明因为在忙着欣赏他的花儿,所以想请你帮他回答这些问题。
小明有一个花园,花园里面一共有m朵花,对于每一朵花,都是不一样的,小明用1~m中的一个整数表示每一朵花。
他很喜欢去看这些花,有一天他看了n次,并将n次他看花的种类是什么按照时间顺序记录下来。
记录用a[i]表示,表示第i次他看了a[i]这朵花。
小红很好奇,她有Q个问题,问[l,r]的时间内,小明一共看了多少朵不同的花儿,小明因为在忙着欣赏他的花儿,所以想请你帮他回答这些问题。
输入两个数n,m;(1<=n<=2000,1<=m<=100);分别表示n次看花,m表示一共有m朵花儿。
接下来输入n个数a[1]~a[n],a[i]表示第i次,小明看的花的种类;
输入一个数Q(1<=Q<=1000000);表示小红的问题数量。
输入Q行 每行两个数l,r(1<=l<=r<=n);表示小红想知道在第l次到第r次,小明一共看了多少不同的花儿。
一共Q行
每一行输出一个数 表示小明在[l,r]的时间内看了多少种花。
5 3 1 2 3 2 2 3 1 4 2 4 1 5
3 2 3
import sys from collections import defaultdict n, m = list(map(int, sys.stdin.readline().split())) a = list(map(int, sys.stdin.readline().split())) Q = int(sys.stdin.readline().strip()) class Solution(object): def matrix_init(self, n, m, a): self.matrix = [[0]*(n-i) for i in range(n)] mydic = defaultdict(int) cur_type = 0 for i in range(n): if not mydic[a[i]]: cur_type += 1 mydic[a[i]] += 1 self.matrix[0][i] = cur_type for i in range(1, n): pop_flag = False target_find_flag = False mydic[a[i-1]] -= 1 if not mydic[a[i-1]]: mydic.pop(a[i-1]) pop_flag = True for j in range(i, n): if a[j] == a[i-1]: target_find_flag = True if j == i: self.matrix[i][j-i] = 1 continue if pop_flag or not target_find_flag: self.matrix[i][j-i] = self.matrix[i-1][j-i+1] - 1 else: self.matrix[i][j-i] = self.matrix[i-1][j-i+1] def print_queries(self): for line in sys.stdin: l, r = list(map(int, line.split())) sys.stdout.write(str(self.matrix[l-1][r-l])+'\n') if __name__ == '__main__': s = Solution() s.matrix_init(n, m, a) s.print_queries()
import java.util.*;
public class Main{
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int m = sc.nextInt();
int []A = new int [n];
int []B = new int [m];
for(int i=0;i<n;i++){
A[i] = sc.nextInt();
}
int Q = sc.nextInt();
int [][]a = new int [Q][2];
for(int i=0;i<Q;i++){
a[i][0] = sc.nextInt();
a[i][1] = sc.nextInt();
}
for(int i=0;i<Q;i++){
int t=0;
for(int j=a[i][0]-1;j<=a[i][1]-1;j++){
int dd = A[j];
if(B[dd-1]!=i+1){
B[dd-1]=i+1;
t++;
}
}
System.out.println(t);
}
}
} 本题经典问题是查询区间不同数量,简单做法是树状数组求法 (还有***树做法
先对询问进行离线。 然后按照右端点从小到大排序。
显然数据范围可以开到 n, k 可以开到 1e6,不然暴力预处理就过了
#include
using namespace std;
const int N = 1e6 + 5;
int a[N];
struct Bit {
int c[N];
int n;
void init() { memset(c, 0, sizeof(c)); }
int lowbits(int x) { return x & -x;}
void add(int i, int v) {
for(; i <= n; i += lowbits(i)) c[i] += v;
}
int get(int i) {
int ans = 0;
if(i <= 0) return 0;
for(; i > 0; i -= lowbits(i)) ans += c[i];
return ans;
}
}B;
struct node {
int l, r, id;
bool friend operator < (node a, node b) {
return a.r < b.r;
}
}b[N];
int id[N], ans[N];
int main()
{
/*
#ifndef ONLINE_JUDGE
freopen("a.txt", "r", stdin);
#endif // ONLINE_JUDGE
*/
int n, m, k;
scanf("%d %d", &n, &k);
B.init();
B.n = n;
memset(id, -1, sizeof(id));
for(int i = 1; i <= n; i++) scanf("%d", &a[i]);
scanf("%d", &m);
for(int i = 1; i <= m; i++) {
int l, r;
scanf("%d %d", &l, &r);
b[i] = {l, r, i};
}
sort(b + 1, b + m + 1);
int j = 1, sum = 0;
for(int i = 1; i <= n; i++) {
if(id[a[i]] != -1) B.add(id[a[i]], -1), sum--;
id[a[i]] = i; sum++;
B.add(i, 1);
while(j <= m && b[j].r == i) {
int tmp = sum - B.get(b[j].l-1);
ans[b[j].id] = tmp;
j++;
}
}
for(int i = 1; i <= m; i++) {
printf("%d\n", ans[i]);
}
return 0;
}
import java.util.*;
public class Main {
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int m = sc.nextInt();
int[] a = new int[n];
// 读取看的次数的种类
for(int i=0;i<n;i++) {
a[i]= sc.nextInt();
}
int q = sc.nextInt();
for(int i=0;i<q;i++) {
int l = sc.nextInt();
int r =sc.nextInt();
System.out.println(test(l,r,a));
}
}
public static int test(int l,int r,int[]a) {
Set<Integer> temp = new HashSet<>();
for(int i=l-1;i<r;i++) {
temp.add(a[i]);
}
return temp.size();
}
}
//用深度优先搜索的简单解法,虽然超时了,但可以看看方法,代码如下。
#include <stdio.h>
int n,m,q,l,r; //题目数据
int t,total=0;
int a[2019];
int v[2019]={0}; //用来标记是否被访问过的数组
void dfs(int l,int r){
if(l==r){ //递归出口,当左等于右时跳出 ,此时在处理最后一个数
if(v[l]==0)
printf("%d\n",total+1); //最后一个数若未访问总数加一
else
printf("%d\n",total); //最后一个数若已访问总数不变
total=0; //数据清零 ,准备处理下一组问题
for(int i=1;i<=n;i++)
v[i]=0;
return;
}
for(int k=l;k<=r;k++){
if(a[k]==a[l]&&v[k]==0){ //标记与第一个数字相等且未被访问过的数字
v[k]=1;
t=2; //如果找到新的未被访问的数字的话让t=2
}
}
if(t==2){ //如果t=2,说明找到新的数字,总数++,再把t初始化
total++;
t=0;
}
dfs(l+1,r); //向右寻找下一个
}
int main(void){
scanf("%d%d",&n,&m); //输入m,n,a[i]
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
}
scanf("%d",&q); //输入Q
for(int i=1;i<=q;i++){
scanf("%d%d",&l,&r); //输入l,r
dfs(l,r); //搜索开始
}
return 0;
} #include <iostream> #include <set> #include <vector> #include <unordered_set> using namespace std; int main(){ int m,n; while(cin >> n >> m){ vector<int> a(n); for(int i = 0; i < n; ++i){ scanf("%d" , &a[i]); } vector<vector<int>> ans(n, vector<int>(n, 1)); // ans[i][j] 表示从时间[i + 1, j + 1]看了几种花,其中i <= j; for(int i = 0; i < n; ++i){ unordered_set<int> set_a; set_a.insert(a[i]); for(int j = i; j < n; ++j){ set_a.insert(a[j]); ans[i][j] = set_a.size(); } } int Q; cin >> Q; while(Q--){ int l, r; scanf("%d %d" , &l, &r); //printf("%d\n",ans[l - 1][r - 1]); //cin >> l >> r; cout << ans[l - 1][r - 1] << endl; } } return 0; }
let nm = readline(); // 第一行
let flowers = readline();
flowers = flowers.split(' '); // 所有看过花的类型
let questions = +readline(); // 问题次数
let duration;
let l,r;
let res = {};
function test () {
duration=readline()
duration = duration.split(' ');
l = +duration[0]-1;
r = +duration[1];
for (let i = l; i < r; i++) {
res[flowers[i]] = 1;
}
res = Object.keys(res);
}
for (let i =0; i < questions;i++) {
test();
print(res.length)
res = {};
} 86.6% 提示超时,大佬们帮忙看看如何优化。
import java.util.*;
public class Main{
public static void main(String[] args) {
Scanner sc= new Scanner(System.in);
int n=sc.nextInt();
int m=sc.nextInt();
int[] a=new int[n];
for(int i=0;i<n;i++){
a[i]=sc.nextInt();
}
int Q=sc.nextInt();
while (Q!=0){
int l=sc.nextInt();
int r=sc.nextInt();
cal(a,l,r,m);
Q--;
}
}
private static void cal(int[] a, int l, int r, int m){
int left=l-1;
int right=r-1;
int len=right-left+1;
int[] num=new int[len];
System.arraycopy(a, 0 + left, num, 0, len);
Arrays.sort(num);
int count=0;
for(int i=0;i<len-1;i++){
if(num[i]!=num[i+1]){
count++;
}
}
System.out.println(count+1);
}
}
import java.util.*;
public class Main{
public static void main(String[] args){
Scanner scn=new Scanner(System.in);
while(scn.hasNextInt()){
int n=scn.nextInt();
int m=scn.nextInt();
byte[] a=new byte[n];
for(int i=0;i<n;i++) a[i]=scn.nextByte();
int q=scn.nextInt();
for(int i=0;i<q;i++){
int l=scn.nextInt();
int r=scn.nextInt();
int t=0;
byte[] c=new byte[m];
for(int j=l-1;j<r;j++) c[a[j]-1]=1;
for(byte cell:c) if(cell==1) t++;
System.out.println(t);
}
break;
}
}
} from collections import defaultdict while True: try: n, m = map(int, input().split()) except: break nums = list(map(int, input().split())) dp = [[0 for _ in range(n)] for _ in range(n)] for i in range(n): dic = defaultdict(int) dic[nums[i]] += 1 dp[i][i] = 1 for j in range(i+1, n): if nums[j] in dic: dp[i][j] = dp[i][j-1] else: dp[i][j] = dp[i][j-1] + 1 dic[nums[j]] += 1 q = int(input()) for _ in range(q): l, r = map(int, input().split()) print(dp[l-1][r-1])
import java.util.Scanner;
public class Flower {
public static void main(String[] args) {
Scanner scanner=new Scanner(System.in);
int n=0,m=0;
n=scanner.nextInt();
m=scanner.nextInt();
int[] a=new int[n+1];
int[] b=new int[m+1];
for(int i=1;i<=n;i++) {
a[i]=scanner.nextInt();
}
int q=scanner.nextInt();
int[] c=new int[q];
for(int i=0;i<q;i++) {
for(int k=0;k<m+1;k++) {
b[k]=0;
}
int t=0;
int l=scanner.nextInt();
int r=scanner.nextInt();
for(int j=l;j<=r;j++) {
if(b[a[j]]!=1) {
t++;
b[a[j]]=1;
}
}
c[i]=t;
}
for(int i=0;i<q;i++)
{
System.out.println(c[i]);
}
}
} #include<stdio.h>
#include<string.h>
#include<stdlib.h>
int main()
{
int n,m;
scanf("%d %d",&n,&m);
int a[n+1];
a[0]=0;
int b[105];
int c[n+1][n+1];
memset(c,0,sizeof(c));
for(int i = 1; i <= n; ++i)
{
scanf("%d",&a[i]);
}
for(int i = 1; i<= n; ++i)
{
memset(b,0,sizeof(b));
for(int j = i; j <= n; ++j)
{
b[a[j]]++;
int num=0;
int count=0;
for(int k = 1; k <= 100; ++k)
{
if(b[k])
{
count+=b[k];
num++;
if(count==j-i+1) break;
}
}
c[i][j]=num;
}
//printf("%d ",num);
}
int Q;
scanf("%d",&Q);
while(Q--)
{
int x,y;
scanf("%d %d",&x,&y);
printf("%d\n",c[x][y]);
}
return 0;
}
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
int n = scan.nextInt();
int m = scan.nextInt();
boolean []check = new boolean[m];
int[] arr = new int[n];
for (int i = 0; i <n; i++) {
arr[i] = scan.nextInt();
}
int q = scan.nextInt();
for (int i = 0; i <q; i++) {
initCheck(check);
int l = scan.nextInt();
int r = scan.nextInt();
int count = 0;
for(int j=l-1;j<r;j++){
if(!check[arr[j]-1]){
check[arr[j]-1]=true;
count++;
}
}
System.out.println(count);
}
}
public static void initCheck(boolean []check){
for(int i=0;i<check.length;i++)
check[i]=false;
}
} public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int m = sc.nextInt();
int[] a = new int[n+1];
int count = 0;
Set<Integer> set = new HashSet<>();
while (++count <= n) {
a[count] = sc.nextInt();
}
int Q = sc.nextInt();
while (Q-- > 0) {
int l = sc.nextInt();
int r = sc.nextInt();
for (int i = l; i <= r; i++) {
set.add(a[i]);
}
System.out.println(set.size());
set.clear();
}
} import java.util.Arrays;
import java.util.Scanner;
/**
* created by LMR on 2019/8/7
*/
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int m = sc.nextInt();
int a[] = new int[n];
int mem[][][] = new int[n][n][m];
for (int i = 0; i < n; i++)
{
a[i] = sc.nextInt();
mem[0][n - 1][a[i] - 1]++;
}
for (int i = n - 1; i >= 0; i--)
for (int j = 0; j < i; j++){
if (j != 0){
mem[j][i] = Arrays.copyOf(mem[j - 1][i], m);
mem[j][i][a[j - 1] - 1]--;
}else {
if (i != n - 1){
mem[j][i] = Arrays.copyOf(mem[j][i + 1], m);
mem[j][i][a[i + 1] - 1]--;
}
}
}
int q = sc.nextInt();
int i = 0;
while (i < q){
int l =sc.nextInt();
int r = sc.nextInt();
if (l == r)
System.out.println(1);
else {
int temp[] = mem[l-1][r-1];
int result = 0;
for (int k : temp)
if (k != 0)
result++;
System.out.println(result);
}
i++;
}
}
}
# 通过87% 最后超内存了 之前的思路是遍历一遍,用dict 保存当前为止出现过得花以及对应的次数 # 超时; 现在是2维遍历,维护一个二维矩阵,表示i到j的种类数,也只通过了87% import sys lines = sys.stdin.readlines() n,m = [int(n) for n in lines[0].strip().split()] c = [int(n) for n in lines[1].strip().split()] qNum = int(lines[2].strip()) q = [] for i in range(3,len(lines)): q.append([int(m) for m in lines[i].strip().split()]) res = [[0 for i in range(n)] for j in range(n)] for i in range(len(c)): s = set() for j in range(i,n): s.add(c[j]) res[i][j] = len(s) for quary in q: l,r = quary[0],quary[1] print(res[l-1][r-1])