本以为这题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 }
T的代码

  

  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 }
AC的代码