//好一段时间没弄了,期末考试去了,手都生了。
题目描述:
给出n个非递减序列数,有Q个询问,l,r表示从l到r的出现次数最多的数的出现次数。
题解:
可以为了省空间而浪费编程复杂度——我不喜欢。
介绍一个很简单的方法:
建立一个线段树,维护三个数据maxlen以mid向两边能得到的最大长度,left以l向右能得到的最大长度,right以r向左能得到的最大长度。
用3个if来维护:
a[mid-1]==a[mid]---->maxlen=max(maxlen,lch.right+rch.left)
a[l]==a[mid]-------->left+=rch.left
a[mid-1]==a[r-1]---->right+=lch.right
看似复杂,其实很好理解,这里就不多说了。
另外,用莫队算法可以解决不单调的,可以百度一下。
参考程序:
#include<cstdio>
#include<algorithm>
#define maxn 150000
#define node 3*maxn+1
using namespace std;
int n,T;
int a[maxn];
struct SegMent{
int left[node],right[node],maxlen[node];
struct TreeNode{
int maxlen,left,right;
operator int(){
return max(maxlen,max(left,right));
}
TreeNode(int maxlen,int left,int right):maxlen(maxlen),left(left),right(right){}
};
void build(int p,int l,int r){
if (l+1==r){
left[p]=right[p]=maxlen[p]=1;
}else{
int pl=2*p,pr=2*p+1;
int mid=(l+r)>>1;
build(pl,l,mid);
build(pr,mid,r);
maxlen[p]=max(maxlen[pl],maxlen[pr]);
left[p]=left[pl];right[p]=right[pr];
if (a[mid-1]==a[mid])
maxlen[p]=max(maxlen[p],right[pl]+left[pr]);
if (a[l]==a[mid])
left[p]+=left[pr];
if (a[mid-1]==a[r-1])
right[p]+=right[pl];
}
}
TreeNode query(int p,int ql,int qr,int l,int r){
if (ql>=r || qr<=l)return TreeNode(0,0,0);else
if (ql<=l && r<=qr)
return TreeNode(maxlen[p],left[p],right[p]);
else{
int pl=2*p,pr=2*p+1;
int mid=(l+r)>>1;
TreeNode lch=query(pl,ql,qr,l,mid),rch=query(pr,ql,qr,mid,r);
TreeNode tmp(max(lch.maxlen,rch.maxlen),lch.left,rch.right);
if (a[mid-1]==a[mid])
tmp.maxlen=max(tmp.maxlen,lch.right+rch.left);
if (a[l]==a[mid])
tmp.left+=rch.left;
if (a[mid-1]==a[r-1])
tmp.right+=lch.right;
return tmp;
}
}
}tree;
int main(){
while (scanf("%d%d",&n,&T)==2 && n){
for (int i=0;i<n;i++)
scanf("%d",&a[i]);
tree.build(1,0,n);
while (T--){
int from,to;
scanf("%d%d",&from,&to);
printf("%d\n",tree.query(1,from-1,to,0,n));
}
}
return 0;
}
还有,将下一程序献给我不屈搏斗又无可奈何Wa的浪费了的时光:
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
#include<vector>
#include<queue>
#define maxn 150000
using namespace std;
int n,T;
int a[maxn];
struct Result{
int maxlen, leftlen, rightlen;
operator int(){
return max(maxlen, max(leftlen, rightlen));
}
Result(){}
Result(int maxlen, int leftlen, int rightlen) : maxlen(maxlen), leftlen(leftlen), rightlen(rightlen){}
};
struct Segment{
int left[3*maxn+1],right[3*maxn+1];
Result tree[3*maxn+1];
void build(int no,int l,int r){
int mid=(l+r)>>1;
left[no]=l;right[no]=r;
if (l+1<r){
build(2*no,l,mid);
build(2*no+1,mid,r);
}
}
void replace(int no,int i,int data){
if (left[no]+1==right[no]){
tree[no].leftlen=1;
tree[no].rightlen=1;
tree[no].maxlen=1;
}else{
int mid=(left[no]+right[no])>>1;
int pl=2*no,pr=2*no+1;
int l=left[no],r=right[no];
if (i<mid)replace(pl,i,data);
else replace(pr,i,data);
tree[no].maxlen=max(tree[pl].maxlen,tree[pr].maxlen);
tree[no].leftlen=tree[pl].leftlen;
tree[no].rightlen=tree[pr].rightlen;
if (a[mid-1]==a[mid]){
tree[no].maxlen=max(tree[no].maxlen,tree[pl].rightlen+tree[pr].leftlen);
}
if (a[l]==a[mid]){
tree[no].leftlen+=tree[pr].leftlen;
}
if (a[mid-1]==a[r-1]){
tree[no].rightlen+=tree[pl].rightlen;
}
}
}
Result query(int no,int l,int r){
if (r<=left[no] || right[no]<=l)return Result(0,0,0);else
if (l<=left[no] && right[no]<=r){
return Result(tree[no].maxlen,tree[no].leftlen,tree[no].rightlen);
}else{
int mid=(left[no]+right[no])>>1;
Result lch=query(2*no,l,r),rch=query(2*no+1,l,r);
Result tmp(max(lch.maxlen,rch.maxlen),lch.leftlen,rch.rightlen);
if (a[mid-1]==a[mid])
tmp.maxlen=max(tmp.maxlen,lch.rightlen+rch.leftlen);
if (a[l]==a[mid])tmp.leftlen+=rch.leftlen;
if (a[mid-1]==a[r-1])tmp.rightlen+=lch.rightlen;
return tmp;
}
}
}Tree;
int main(){
freopen("in.in","r",stdin);
freopen("out.out","w",stdout);
while (scanf("%d%d",&n,&T)==2 && n){
Tree.build(1,0,n);
for (int i=0;i<n;i++){
scanf("%d",&a[i]);
Tree.replace(1,i,a[i]);
}
while (T--){
int from,to;
scanf("%d%d",&from,&to);
printf("%d\n",Tree.query(1,from-1,to));
}
}
return 0;
}