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

最长子串

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 5
1 2 3 2 1
1 2
1 3
2 3 1
1 2
1 3

Sample Output

3
1
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++;
		else
		break;
	}
	return right;
}
//得出i左侧>=a【i】的个数
int getLeftCount(int pos,int i)
{
	int left=0;
	while(pos>=0)
	{
		pos--;
		if(a[pos]>=a[i])
		left++;
		else
		break;
	}
	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;
}
时间: 2024-08-01 05:52:41

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

补番计划 (长沙理工大学第十一届程序设计竞赛)(双端队列+set容器+string)

补番计划 Time Limit : 4000/2000ms (Java/Other)   Memory Limit : 65535/32768K (Java/Other) Total Submission(s) : 8   Accepted Submission(s) : 1 Font: Times New Roman | Verdana | Georgia Font Size: ← → Problem Description 阿聪是一个日漫狂魔.暑假在家的时候,他有12小时在补番,12小时在睡

开锁魔法II 哈尔滨理工大学第五届ACM程序设计竞赛

规律:a[i][j]=     1/i * a[i-1][j-1]      +      (i-1)/i * a[i-1][j];  (少一个盒子时使用j-1 次魔法的概率)   (少一个盒子时使用j次魔法的概率) 公式推导如下: 设a[i][j]为打开i个盒子正好需要j次魔法的情况. ① 1->1 ② 1->1 , 2->2;        两次 1->2 , 2->1;        一次 ③ 1->1 , 2->2 , 3->3;     三次 1-

2015年江西理工大学C语言程序设计竞赛(初级组)

JankTao相亲记 解法:排序 #include<stdio.h> #include<string.h> #include<iostream> #include<math.h> #include<map> #include<set> #include<vector> #include<algorithm> using namespace std; const double INF = 1e20; const

2016年江西理工大学C语言程序设计竞赛(初级组)

Problem Description 华盛顿在寝室洗衣服,遭到了xyf的嫌弃,于是xyf出了道题给华盛顿来做(然而并没有什么关系-v-!)xyf扔给华盛顿n个字符串,这些字符串的长度不超过10000并且没有空串.有Q个询问,每个询问一个k,求出这n个字符串中的子串包含了第k个字符串的个数(详情请看hint) Input 多组测试.每组测试先输入n,Q表示n个字符串,Q个询问.(1<= n ,Q <=1e4)接下来n行每行一个字符串si,(1<= |si| <= 1e4)再接下来Q

2015年江西理工大学C语言程序设计竞赛(高级组)

A 解法:DP+二分 dp[i]=max(dp[i],dp[j]+p[i].v)(i>j) dp[i]表示建立i点之后能够获得的最大值 int n,M; struct node { int l,v; }p[1010]; int dp[1010]; bool cmp(node a,node b){ return a.l < b.l; } bool judge_oo(){ int Max = -1; for(int i = 1;i <= n;i++) Max = max(Max,p[i].v

福州大学第十一届程序设计竞赛

Problem 2167 大王叫我来巡山呐 Problem 2168 防守阵地 I 直接前缀和预处理 Problem 2169 shadow  .. Problem 2170 花生的序列 dp Problem 2171 防守阵地 II 线段树搞搞 Problem 2172 巡了南山我巡北山 http://blog.csdn.net/my_acm_dream/article/details/44507371 好题 Problem 2173 Nostop 矩阵高速幂 Problem 2174 卷福的

2013年江西理工大学C语言程序设计竞赛(初级组)

ACM ICPC WORLD FINAL 解法:排序大家都知道,去重的话,初学者用数组就好了 #include<algorithm> #include<iostream> using namespace std; int main() { int a,b,c[100],i,d[31]; cin>>a; while(a>0) { cin>>b; for(i=0;i<31;i++) d[i]=0; for(i=0;i<b;i++) { cin&

福州大学第十一届程序设计竞赛菜鸟的题解

前几天去了两个比较牛的互联网公司面试,在sql这块都遇到问题了,哎,可惜呀,先把简单的梳理一下 成绩表 score 1.group by 使用 按某一个维度进行分组 例如: 求每个同学的总分 SELECT student,SUM(score) FROM score GROUP BY student 求每个同学的平均分 SELECT student,AVG(score) FROM score GROUP BY student 也可以按照 班级,课程 来求 2.having 与 where的区别 h

2017年江西理工大学C语言程序设计竞赛(高级组)

问题 A: 求近似值 1 #include <stdio.h> 2 #include <time.h> 3 #include <stdlib.h> 4 using namespace std; 5 6 #define ll long long 7 const ll M = 9e18; 8 const ll MOD = 9932017; 9 struct Node { 10 ll m[2][2]; 11 }; 12 13 ll a[4966010]; 14 15 Node