poj 3368Frequent values 线段树

    技术2022-05-20  50

     

    Frequent values Time Limit: 2000MS Memory Limit: 65536KTotal Submissions: 7308 Accepted: 2615

    Description

    You are given a sequence of n integers a1 , a2 , ... , an in non-decreasing order. In addition to that, you are given several queries consisting of indices i and j (1 ≤ i ≤ j ≤ n). For each query, determine the most frequent value among the integers ai , ... , aj.

    Input

    The input consists of several test cases. Each test case starts with a line containing two integers n and q (1 ≤ n, q ≤ 100000). The next line contains n integers a1 , ... , an (-100000 ≤ ai ≤ 100000, for each i ∈ {1, ..., n}) separated by spaces. You can assume that for each i ∈ {1, ..., n-1}: ai ≤ ai+1. The following q lines contain one query each, consisting of two integers i and j (1 ≤ i ≤ j ≤ n), which indicate the boundary indices for the query.

    The last test case is followed by a line containing a single 0.

    Output

    For each query, print one line with one integer: The number of occurrences of the most frequent value within the given range.

    Sample Input

    10 3 -1 -1 1 1 1 1 3 10 10 10 2 3 1 10 5 10 0

    Sample Output

    1 4 3

    Source

    Ulm Local 2007 #include<cstdio> #include<cstring> #define LL(x) ((x)<<1) #define RR(x) ((x)<<1|1) #define mmax(a,b) ((a)>(b)?(a):(b)) const int MAXN=100000+10; int a[MAXN],hash[MAXN]; int t,n; struct Point { int left,right; int count,num; } point[MAXN]; struct Node { int left,right; int count,num; int clam() { return (left+right)>>1; } } tree[MAXN*3]; void init() //离散化,相同的点缩成一点,记录区间左端点,右端点,出现次数,和数字 { point[1].num=a[1]; point[1].left=1; point[1].right=1; point[1].count=1; hash[1]=1; t=1; for(int i=2; i<=n; i++) { if(a[i]==a[i-1]) { point[t].count++; point[t].right=i; } else { point[++t].left=i; point[t].right=i; point[t].num=a[i]; point[t].count=1; } hash[i]=t; } } void build(int left,int right,int idx) { tree[idx].left=left; tree[idx].right=right; if(left==right) { tree[idx].count=point[left].count;//不可能出现其他相同的了 tree[idx].num=point[left].num; return; } int mid=tree[idx].clam(); build(left,mid,LL(idx)); build(mid+1,right,RR(idx)); if(tree[LL(idx)].count>tree[RR(idx)].count) { tree[idx].count=tree[LL(idx)].count; tree[idx].num=tree[LL(idx)].num; } else { tree[idx].count=tree[RR(idx)].count; tree[idx].num=tree[RR(idx)].num; } } int query(int left,int right,int idx) { if(left<=tree[idx].left&&right>=tree[idx].right) { return tree[idx].count; } int mid=tree[idx].clam(); if(left>mid) return query(left,right,RR(idx)); else if(right<=mid) return query(left,right,LL(idx)); else { int a=query(left,mid,LL(idx)); int b=query(mid+1,right,RR(idx)); return mmax(a,b); //return mmax(query(left,mid,LL(idx)),query(mid+1,right,RR(idx))); } } int solve(int a,int b) { if(hash[a]==hash[b]) return b-a+1; else if(hash[a]+1==hash[b]) { int l=point[hash[a]].right-a+1; int r=b-point[hash[b]].left+1; return mmax(l,r); } else { int l=point[hash[a]].right-a+1; int r=b-point[hash[b]].left+1; l=mmax(l,r); r=query(hash[a]+1,hash[b]-1,1); l=mmax(l,r); return l; } } int main() { int q; while(scanf("%d",&n)!=EOF) { if(n==0) break; scanf("%d",&q); for(int i=1; i<=n; ++i) scanf("%d",&a[i]); init(); build(1,t,1); while(q--) { int a,b; scanf("%d%d",&a,&b);//在原序列中的区间,判断再转化为线段树上的区间 printf("%d/n",solve(a,b)); } } return 0; }  

     


    最新回复(0)