【线段树】FREQUENT - Frequent values(luogu-SP1684 / poj 3368)
生活随笔
收集整理的這篇文章主要介紹了
【线段树】FREQUENT - Frequent values(luogu-SP1684 / poj 3368)
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
FREQUENT - Frequent values
luogu-SP1684
poj 3368
題目大意:
有一個單調(diào)不降序列,讓你求出某些區(qū)間內(nèi)的出現(xiàn)次數(shù)最多的數(shù)出現(xiàn)的次數(shù)(有多組數(shù)據(jù),以0結(jié)尾)
輸入樣例
10 3 -1 -1 1 1 1 1 3 10 10 10 2 3 1 10 5 10 0輸出樣例
1 4 3數(shù)據(jù)范圍:
1≤n,q≤1000001 ≤ n, q ≤ 1000001≤n,q≤100000
?100000≤ai≤100000-100000 ≤ a _{i} ≤ 100000?100000≤ai?≤100000
解題思路:
用線段樹,同時要保存左邊數(shù)字出現(xiàn)的次數(shù),和右邊數(shù)字出現(xiàn)的次數(shù),如果中間相等,就可以嘗試拼接
代碼:
#include<cstdio> #include<cstring> #include<iostream> #define max(x,y) (x)>(y)?(x):(y) using namespace std; int n,m,x,y,s[100500]; struct rec {int l,r,num,ls,rs; }tree[800500]; void up(int dep,int mid)//傳遞 {tree[dep].num=max(tree[dep*2].num,tree[dep*2+1].num);tree[dep].ls=tree[dep*2].ls;//ls是左邊的數(shù)出現(xiàn)的次數(shù)tree[dep].rs=tree[dep*2+1].rs;//rs是右邊的數(shù)出現(xiàn)的次數(shù)if (s[mid]==s[mid+1])tree[dep].num=max(tree[dep].num,tree[dep*2].rs+tree[dep*2+1].ls);//如果可以就合并if (s[tree[dep].l]==s[mid+1])tree[dep].ls+=tree[dep*2+1].ls;//同上if (s[mid]==s[tree[dep].r])tree[dep].rs+=tree[dep*2].rs;return; } void make(int dep)//建樹 {if (tree[dep].l==tree[dep].r){tree[dep].num=1;tree[dep].ls=1;tree[dep].rs=1;return;}int mid=(tree[dep].l+tree[dep].r)>>1;tree[dep*2].l=tree[dep].l,tree[dep*2].r=mid;tree[dep*2+1].l=mid+1,tree[dep*2+1].r=tree[dep].r;make(dep*2);make(dep*2+1);up(dep,mid);return; } int find(int dep,int l,int r) {if (tree[dep].l==l&&tree[dep].r==r) return tree[dep].num;if (tree[dep].l>=tree[dep].r) return 0;int mid=(tree[dep].l+tree[dep].r)>>1,sum=1,sum1=1;if (r<=mid) return find(dep*2,l,r);//在左邊if (l>mid) return find(dep*2+1,l,r);//在右邊if (s[mid]==s[mid+1]) sum=min(mid-l+1,tree[dep*2].rs)+min(r-mid,tree[dep*2+1].ls);//合并sum1=max(find(dep*2,l,mid),find(dep*2+1,mid+1,r));//去一個更優(yōu)的return max(sum,sum1);//兩種方法選一種 } int main() {while(scanf("%d",&n),n)//多組數(shù)據(jù){memset(tree,0,sizeof(tree));scanf("%d",&m);for (int i=1;i<=n;++i)scanf("%d",&s[i]);tree[1].l=1;tree[1].r=n;make(1);for (int i=1;i<=m;++i){scanf("%d %d",&x,&y);printf("%d\n",find(1,x,y));}} }總結(jié)
以上是生活随笔為你收集整理的【线段树】FREQUENT - Frequent values(luogu-SP1684 / poj 3368)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 让系统流畅起来如何让电脑更流畅
- 下一篇: 惠普发布战99 Monster满血高算工