题意:给定两个含n个元素的数组a,b,数组中不含相同元素,求最大的p(p<=n),使得a和b等价,这里等价的定义为a[l,r]和b[l,r]的最小值下标相等(1<=l<=r<=p)。
题解:
1、p的范围是1~n,从小到大遍历,利用单调栈求出La[i],表示第一个比a[i]小的元素的下标,Lb[i]同理。对第i个元素来说,如果Lu[i]!=Lv[i],说明包含i在内的区间不满足上述条件,那么p最大只能取i-1。
AC代码:
1 #include<iostream> 2 #include<sstream> 3 #include<fstream> 4 #include<algorithm> 5 #include<string> 6 #include<cstring> 7 #include<iomanip> 8 #include<cstdlib> 9 #include<cctype> 10 #include<vector> 11 #include<cmath> 12 #include<ctime> 13 #include<stack> 14 #include<queue> 15 #include<map> 16 #include<set> 17 #define mem(a,b) memset(a,b,sizeof(a)) 18 #define random(a,b) (rand()%(b-a+1)+a) 19 #define ull unsigned long long 20 #define e 2.71828182 21 #define Pi acos(-1.0) 22 using namespace std; 23 const int MAXN=1e5+5; 24 int n,a[MAXN],b[MAXN]; 25 int La[MAXN],Lb[MAXN]; 26 stack<int> sa,sb; 27 int read() 28 { 29 int s=1,x=0; 30 char ch=getchar(); 31 while(!isdigit(ch)) {if(ch=='-') s=-1;ch=getchar();} 32 while(isdigit(ch)) {x=10*x+ch-'0';ch=getchar();} 33 return x*s; 34 } 35 void init() 36 { 37 while(!sa.empty()) sa.pop(); 38 while(!sb.empty()) sb.pop(); 39 for(int i=1;i<=n;++i) 40 { 41 while(!sa.empty()&&a[i]<a[sa.top()]) sa.pop(); 42 if(sa.empty()) La[i]=0; 43 else La[i]=sa.top(); 44 sa.push(i); 45 } 46 for(int i=1;i<=n;++i) 47 { 48 while(!sb.empty()&&b[i]<b[sb.top()]) sb.pop(); 49 if(sb.empty()) Lb[i]=0; 50 else Lb[i]=sb.top(); 51 sb.push(i); 52 } 53 } 54 int main() 55 { 56 ios::sync_with_stdio(false); 57 cin.tie(0);cout.tie(0); 58 while(~scanf("%d",&n)) 59 { 60 getchar(); 61 for(int i=1;i<=n;++i) a[i]=read(); 62 for(int i=1;i<=n;++i) b[i]=read(); 63 int ans=n; 64 init(); 65 for(int i=2;i<=n;++i) 66 { 67 if(La[i]!=Lb[i]) 68 { 69 ans=i-1; 70 break; 71 } 72 } 73 cout<<ans<<endl; 74 } 75 }
2、笛卡尔树做法
Integration |