题目地址:HDU 4908
这个题是从m开始,分别往前DP和往后DP,如果比m大,就比前面+1,反之-1.这样的话,为0的点就可以与m这个数匹配成一个子串,然后左边和右边的相反数的也可以互相匹配成一个子串,然后互相的乘积最后再加上就行了。因为加入最终两边的互相匹配了,那就说明左右两边一定是偶数个,加上m就一定是奇数个,这奇数个的问题就不用担心了。
代码如下:
#include <iostream> #include <stdio.h> #include <string.h> #include <stdlib.h> #include <math.h> #include <ctype.h> #include <queue> #include <map> #include<algorithm> using namespace std; __int64 dp[50000], a[50000], b1[50000], b2[50000], c1[50000], c2[50000]; int main() { __int64 n, m, i, pos, s, s1, s2; while(scanf("%I64d%I64d",&n,&m)!=EOF) { s=0; memset(b1,0,sizeof(b1)); memset(c1,0,sizeof(c1)); memset(b2,0,sizeof(b2)); memset(c2,0,sizeof(c2)); for(i=0;i<n;i++) { scanf("%I64d",&a[i]); if(a[i]==m) pos=i; } dp[pos]=0; s=1; s1=s2=0; for(i=pos+1;i<n;i++) { if(a[i]>m) { dp[i]=dp[i-1]+1; } else { dp[i]=dp[i-1]-1; } if(dp[i]==0) { s1++; } else if(dp[i]>0) { b1[dp[i]]++; } else { b2[-dp[i]]++; } } for(i=pos-1;i>=0;i--) { if(a[i]>m) { dp[i]=dp[i+1]+1; } else { dp[i]=dp[i+1]-1; } if(dp[i]==0) { s2++; } else if(dp[i]>0) { c1[dp[i]]++; } else { c2[-dp[i]]++; } } s+=s1+s2+s1*s2; for(i=1;i<=40000;i++) { s+=b1[i]*c2[i]; s+=b2[i]*c1[i]; } printf("%I64d\n",s); } return 0; }
HDU 4908 (杭电 BC #3 1002题)BestCoder Sequence(DP),布布扣,bubuko.com
时间: 2024-10-02 00:21:50