最长子串(长沙理工大学第十一届程序设计竞赛 离线 做了n天.....崩溃了)

来源:互联网 发布:ug车床编程 编辑:程序博客网 时间:2024/04/28 08:54

最长子串

Time Limit : 4000/2000ms (Java/Other)   Memory Limit : 65535/65535K (Java/Other)
Total Submission(s) : 27   Accepted Submission(s) : 4

Font: Times New Roman | Verdana | Georgia

Font Size:  

Problem Description

小E最近开始研究数列,于是小J就给他出了一道题目:给你一个长度为n的数列A(下标从1开始),然后在给你m个询问,有两种询问
第一种 输入1 x 找到数列的一个最长连续子串,使得这个连续子串的里面的每个数都大于等于x。
第二种 输入2 x y 把数列中x的位置的值修改为y。(对于第二种询问次数不会超过10)
对于每个询问1输出最长连续子串的长度。
子串的含义是数列中一段连续的数。
其中 1< n <= 100000 1 < m <= 10000 0 <= Ai <= 100000

Input

多组输入,每组数据第一行为n m,表示数列的长度和询问的次数
接下来m行,表示m次询问,只有2种格式,详细见描述

Output

如果询问的类型为查询,则输出一行,表示最长连续子串的长度
如果询问的类型为修改,则无需输出

Sample Input

5 51 2 3 2 11 21 32 3 11 21 3

Sample Output

31 1 0

Statistic | Submit | Back

这道题我做了n天啊。。

在acm群里面问  有人说for循环  也有人说线段树  也有人动态规划。。。等等

唉  前两种早就用过了  那么简单的话我也不好意思问啊  

在csdn博客里面问  结果发现都是机器人回答的  回答的是最长公共子序列  我都醉了   可能是看题目是最长子串吧

在百度上问  由于没有积分 无人问津  

在qq问问上 也没有人回答

最后在acm贴吧里面问的

吧主回复了一句

acdream群今天讨论过
当成10个test做
用并查集从大到小合并,离线做。

给了我很大启发,于是终于ac了 唉


题解:

从所给的数列从下标i=0开始 分别向左向右查找大于或等于a[i]的个数n 记为count[i]=n

如果a[i+1]>a[i] 只向右查找大于等于a[i+1]的个数n,count[i]=n

如果a[i+1]=a[i]  ,count[i+1]=count[i]

如果a[i+1]<a[i],分别向左向右查找大于或等于a[i]的个数n 记为count[i]=n

然后用一个数组存贮当前值得子序列个数  result[a[i]]=getMax(result[a[i]],coun[i]);

最后对result数组进行处理  你该问为什么处理了  因为当我们这样查找的时候如果count[5]<count[6]  我们要是查找1  5  输出count[5]就打错特错了

因为6>5 啊  懂了吧 

看代码吧  累死了。。


#include <stdio.h>#include <string.h>#include <algorithm>using namespace std;int coun[100000+10];int a[100000+10];int result[100000+10];int n,m;int allMax;int getMax(int x,int y){return x>y?x:y;}//得出i右侧>=a【i】的个数 int getRightCount(int pos,int i){int right=0;while(pos<n){pos++;if(a[pos]>=a[i])right++;elsebreak;}return right;}//得出i左侧>=a【i】的个数 int getLeftCount(int pos,int i){int left=0;while(pos>=0){pos--;if(a[pos]>=a[i])left++;elsebreak;}return left;}//对count数组进行处理 void manage(){int Max=result[allMax];for(int i=allMax;i>=0;i--){result[i]=max(result[i],Max);Max=result[i];}}//求count[i] void init(){memset(coun,0,sizeof(coun));memset(result,0,sizeof(result));result[0]=n;allMax=0;for(int i=0;i<n;i++){if(allMax<a[i])allMax=a[i];if(i==0){coun[i]=getRightCount(i,i)+1;}else if(a[i]==a[i-1]){coun[i]=coun[i-1];}else if(a[i]>a[i-1]){coun[i]=getRightCount(i,i)+1;}else if(a[i]<a[i-1]){coun[i]=getRightCount(i,i)+getLeftCount(i,i)+1;}result[a[i]]=getMax(result[a[i]],coun[i]);}manage();}int main(){while(~scanf("%d %d",&n,&m)){memset(a,0,sizeof(a));for(int i=0;i<n;i++)scanf("%d",&a[i]);init();for(int i=0;i<m;i++){int x;scanf("%d",&x);if(x==1){int y;scanf("%d",&y);printf("%d\n",result[y]);}if(x==2){int pos,x;scanf("%d %d",&pos,&x);a[pos-1]=x;init();}}}return 0;}


1 0