本以为这题n=3000,随便n方一下就能过。于是我先枚举长度len再枚举起点,不断增加新的点并删除原来的点,判断在b中的r-l+1是不是等于len即可,这个过程显然要用set维护比较方便,但是貌似卡了这个log,T了= =。
然后修改了一下思路,先枚举左端点,再不断的向有扩张,并用两个变量l和r来标记在b中的最左和最右的位置,然后如上做法即可。这样的好处在于不需要删除点的信息,因此可以直接借用变量来维护边界了。具体差别见代码吧。
T的代码如下:
1 #include <stdio.h> 2 #include <algorithm> 3 #include <string.h> 4 #include <set> 5 using namespace std; 6 const int N = 3000 + 5; 7 typedef long long ll; 8 9 int n,a[N],b[N]; 10 int pos[N]; 11 12 int main() 13 { 14 while(scanf("%d",&n) == 1 && n) 15 { 16 for(int i=1;i<=n;i++) scanf("%d",a+i); 17 for(int i=1;i<=n;i++) scanf("%d",b+i), pos[b[i]] = i; 18 ll ans = 0; 19 for(int len=2;len<=n;len++) 20 { 21 set<int> S; 22 for(int i=1;i<=len;i++) 23 { 24 S.insert(pos[a[i]]); 25 } 26 if(*S.rbegin() - *S.begin() + 1 == len) ans++; 27 28 for(int i=len+1;i<=n;i++) 29 { 30 S.insert(pos[a[i]]); 31 S.erase(pos[a[i-len]]); 32 if(*S.rbegin() - *S.begin() + 1 == len) ans++; 33 } 34 } 35 printf("%lld\n",ans); 36 } 37 return 0; 38 }
AC的代码如下:
1 #include <stdio.h> 2 #include <algorithm> 3 #include <string.h> 4 #include <set> 5 using namespace std; 6 const int N = 3000 + 5; 7 typedef long long ll; 8 9 int n,a[N],b[N]; 10 int pos[N]; 11 12 int main() 13 { 14 while(scanf("%d",&n) == 1 && n) 15 { 16 for(int i=1;i<=n;i++) scanf("%d",a+i); 17 for(int i=1;i<=n;i++) scanf("%d",b+i), pos[b[i]] = i; 18 ll ans = 0; 19 for(int i=1;i<=n;i++) 20 { 21 int l = pos[a[i]]; 22 int r = pos[a[i]]; 23 for(int j=i+1;j<=n;j++) 24 { 25 l = min(l, pos[a[j]]); 26 r = max(r, pos[a[j]]); 27 if(r - l == j - i) ans++; 28 } 29 } 30 printf("%lld\n",ans); 31 } 32 return 0; 33 }