区间求最值 |
Problem description |
给定一个长度为N 的数组,有q个询问。每一个询问是求在数组的一段区间内那个元素的因子的个数最大,比方24的因子的个数就是8。
|
Input |
首先是一个整数t,表示有t组測试数据,每组測试数据的第一行是一个整数N(1<=N<=10^6),第二行有N个整数ai(1<=ai<=10^6,i=1,2,.....N)表示数组的元素。第三行有一个整数q(1<=q<=10^5),代表有q个询问,接下来每一行有两个整数,li,ri(li<=ri,li>=1,ri<=N).代表数组的一段区间,而且li+1>=li,ri+1>=ri。 |
Output |
对于每组数据的每一个询问都输出一个整数表示在这段区间里面元素因子个数的最大值。
|
Sample Input |
|
Sample Output |
|
Problem Source |
zkw线段树:
//20716KB 781ms #include <iostream> #include <stdio.h> #include <string.h> using namespace std; #define N 1000010 int T[N*4],M; int yin[N]; void inti() { int i,j; yin[1]=0; for(i=1;i<N;i++) { for(j=i;j<N;j+=i)yin[j]++; } // for(i=0;i<100;i++)printf("%d %d\n",i,yin[i]); } void seg_build(int n){ int i,x; for(M=1;M<=n+1;M*=2); for(i=1+M;i<=n+M;i++){ scanf("%d",&x); T[i]=yin[x]; } for(i=M-1;i;i--) T[i]=max(T[i*2],T[i*2+1]); } int seg_query(int s,int t){ int maxc=-1; for(s=s+M-1,t=t+M+1;s^t^1;s/=2,t/=2){ if(s%2==0) maxc=max(maxc,T[s^1]); if(t%2==1) maxc=max(maxc,T[t^1]); } return maxc; } int main() { inti(); int n,m,a,b; int t; scanf("%d",&t); while(t--){ scanf("%d",&n); memset(T,0,sizeof(T)); seg_build(n); scanf("%d",&m); while(m--){ scanf("%d%d",&a,&b); printf("%d\n",seg_query(a,b)); } } return 0; }
BESTCODE ROUND #2
TIANKENG’s restaurant
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/65536 K (Java/Others)
Total Submission(s): 1361 Accepted Submission(s): 246
Each cases has a positive integer n(1<=n<=10000), which means n groups of customer. Then following n lines, each line there is a positive integer Xi(1<=Xi<=100), referring to the sum of the number of the ith group people, and the arriving time STi and departure time Edi(the time format is hh:mm, 0<=hh<24, 0<=mm<60), Given that the arriving time must be earlier than the departure time.
Pay attention that when a group of people arrive at the restaurant as soon as a group of people leaves from the restaurant, then the arriving group can be arranged to take their seats if the seats are enough.
一维区间更新+求全局最值
#include<iostream> #include<cstdio> #include<cstring> using namespace std; const int N=24*60; int dp[N]; int main() { int t; cin>>t; while(t--) { int m,i,val,h1,h2,m1,m2; char t1[10],t2[10]; memset(dp,0,sizeof(dp)); scanf("%d",&m); for(i=0;i<m;i++) { scanf("%d%s%s",&val,t1,t2); sscanf(t1,"%d:%d",&h1,&m1); sscanf(t2,"%d:%d",&h2,&m2); dp[h1*60+m1]+=val; dp[h2*60+m2]+=-val; } int ma=0; for(i=0;i<24*60;i++){ dp[i]=dp[i-1]+dp[i]; ma=dp[i]>ma?dp[i]:ma; } printf("%d\n",ma); } return 0; }
ZOJ2956方法同上
题意:平面上有n条竖的线段,问水平看过去最多有几条是重叠的
#include<iostream> #include<cstdio> #include<cstring> using namespace std; int main() { int T; scanf("%d",&T); while(T--) { int n,a[10010],x,y1,y2,i,ind; memset(a,0,sizeof(a)); scanf("%d",&n); ind=0; while(n--) { scanf("%d%d%d",&x,&y1,&y2); a[y1]+=1; a[y2+1]-=1; if(y2>ind)ind=y2; } int sum=0,ma=0; for(i=0;i<ind+2;i++){ sum+=a[i]; if(sum>ma)ma=sum; } printf("%d\n",ma); } return 0; }