poj之旅——3368

来源:互联网 发布:恶意百度点击软件 编辑:程序博客网 时间:2024/06/05 19:45

//好一段时间没弄了,期末考试去了,手都生了。


题目描述:

给出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+1using 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);elseif (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 150000using 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);elseif (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;}


0 0
原创粉丝点击