poj3368Frequent values

    技术2022-05-19  30

    思路:因为是 in non-decreasing order,所以把相同的数据统计在一个区间里,则产生j个区间,每个区间记录在原数列的左右序列号以及该区间的长度(即数字的数目)。原序列的序列号都映射入相应的区间,则对于i,j,如果在同一个区间里,则输出j-i+1,如果在相邻的区间里,则max(j-val[map[j]].head+1,val[map[i]].tail-i+1),如果不是相邻的区间,则中间的区间用线段树求出最大值,再和”两边的剩余“比大小

    #include<iostream> using namespace std; #define maxn 100005 struct TREE { int l,r,cover; }; struct node { int head,tail,num; }; TREE st[maxn*4]; node val[maxn]; int sou[maxn],map[maxn]; int mymax(int a,int b) { return a>b?a:b; } int threemax(int a,int b,int c) { return mymax(mymax(a,b),c); } void build(int l,int r,int i) { st[i].l=l,st[i].r=r; if(l==r) { st[i].cover=val[l].num; return ; } if(l<r) { int mid=(l+r)/2; build(l,mid,2*i); build(mid+1,r,2*i+1); st[i].cover=mymax(st[i*2].cover,st[2*i+1].cover); } } int query(int left,int right,int i) { if(st[i].l>=left&&st[i].r<=right) return st[i].cover; int mid=(st[i].l+st[i].r)/2; if(right<=mid) query(left,right,2*i); else if(left>mid) query(left,right,2*i+1); else return mymax(query(left,mid,2*i),query(mid+1,right,2*i+1)); } void init(int n) { int head=1,tail=1,j=0,i,k; while(tail<=n) { while(sou[head]==sou[tail]&&tail<=n) tail++; val[j].head=head; val[j].tail=tail-1; val[j].num=tail-head; j++; head=tail; } for(i=0;i<j;i++) for(k=val[i].head;k<=val[i].tail;k++) map[k]=i; build(0,j-1,1); return ; } int main() { int n,i,j,q,t; while(scanf("%d",&n),n) { scanf("%d",&q); for(i=1;i<=n;i++) scanf("%d",sou+i); init(n); while(q--) { scanf("%d%d",&i,&j); if(map[i]==map[j]) printf("%d/n",j-i+1); else if(map[j]-map[i]==1) { t=mymax(j-val[map[j]].head+1,val[map[i]].tail-i+1); printf("%d/n",t); } else { t=threemax(j-val[map[j]].head+1,val[map[i]].tail-i+1, query(map[i]+1,map[j]-1,1)); printf("%d/n",t); } } } return 0; }


    最新回复(0)