Contest description
Fairy Spirit Witch Dew, the enthusiasm for magic is beyond ordinary people, if found out what the ancient legacy of magic, she always find ways to obtain, and then research and analysis. And recently, he got a "strange" magic scroll from the evil mage Waika.
This magic scroll has a large number of numbers, and according to the scrolls, the Power index of this magic is derived from the number of "magic bands" in this series of numbers;
The so-called "magic interval" refers to a continuous closed interval, and all the numbers on this interval are not the same;
Now, Lulu wants to know the Power index of this magic, can you help her?
Input
Enter a positive integer t to indicate the number of samples, 1≤t≤10.
for each example , first enter a positive integer n, which represents the number of digits on the reel (1≤ n≤ 106 );
then enter n integers, number aI of I, the number of I on the reel (0≤ai≤6).
Output
For each sample, output a positive integer, the power exponent.
The title guarantees the result within the INT range.
Sample input
1
3
1 2 3
Sample output
6
Tips
Please use scanf () to read the data.
For the example, there is a total of {1},{2},{3},{1,2},{2,3},{1,2,3},6 Magic bands, so the Power is 6.
Idea: This problem data range is 1000000, theoretically allow the maximum time complexity of Nlog (n) below, first consider using dynamic programming solution. The goal of the dynamic programming is to find the state transition equation, assuming that a total of n numbers in the array num[n], which contains the solution of the first I number Answer[i], then we are to find the state transfer equation T, so that Answer[i+1]=t (Answer[i]) (1) What kind of relationship is there between answer[i+1] and answer[i+1]?
Obviously, the "magical space" created by the former i+1 number must contain the "magical space" created by the first I, and there is a part of the magic space that contains the number I numbers. In other words, (1) can be further written as: Answer[i+1]=answer[i]+f (i+1) (2) where F (i+1) is the number of magical spaces that contain the number of i+1. So the goal of this problem is further translated into: when we have i+1 a number, what is the magical space that contains the i+1 number?
Of course, we can start with the number of i+1, one to add the number to the empty set, until the collection cannot maintain no duplicate number, then the length of this set is the number of sequences containing the number of i+1 (all sequences are sequentially suffix subsequence). For a sequence of length 4 1 2 3 1 For example when 3 numbers are included, the number of magical spaces is 6.1, 2, 3, 12, 23,123. When the fourth number is added, 231,31,1 (unlike the first 1) is added, so 1 2 3 1 has a magic space of 9. Optimization of the process of F, you can try to take some clever approach. It is unwise to keep adding numbers and checking the sequence every time.
When we go backwards from the I-number, it is obvious to a position J, and Num[j]==num[i] must stop, because the collection has been duplicated. Then we may not be able to exceed the J position when we backtrack from the i+1. (because it still contains num[i] This number, it is duplicated with num[j]. We set the first number of the previous number of the same value in the same position as mark[i]. So in each backtracking, we can set a value of limit (initially 0), indicating the most forward position we can reach. Then in the process of backtracking, for each k (k<i+1), we update the limit if (Mark[k]>limit). Because we cannot exceed mark[k] this position. Then the backtracking will end in the following conditions: limit or num[k]==num[i+1]. The distance from the backtracking is also F (i+1). So we get the complete equation of state transfer.
The code completed by the above ideas is as follows:
#include <iostream> #include <algorithm>using namespace std;int f (int n) {return (n+1) *N/2;} int Num[1000000];int Mark[1000000];int Main () {int i,j,n,t; scanf ("%d", &t); cin>>t; while (t--) {cin>>n; memset (Mark,0,sizeof (Mark)); for (i=0;i<n;i++) {scanf ("%d", &num[i]); cin>>num[i]; } int sum=0; for (i=0;i<n;i++) {int temp=0; int limit=0; for (j=i-1;j>=limit;j--) {if (num[j]==num[i]) break; temp++; if (mark[j]>limit) limit=mark[j]; } mark[i]=j+1; cout<<i<< "" <<temp+1<<endl; sum+=temp+1; }//cout<< "limit:"; for (i=0;i<n;i++)//cout<<mark[i]<< ""; cout<<endl; cout<<sum<<Endl }}
Further optimization Unfortunately, the above algorithm has a tle (time LIMIT exceed) on the South Mail ACM system. Looking back at our approach and our intentions, we will find that if we are faced with n completely different numbers, then each time in the first position the distance will be I, the time complexity of the algorithm is the dreaded On2.
Look where we're stupid.
The foolish place is the bold word in the last paragraph:
When we go backwards from the I-number, it is obvious to a position J, and Num[j]==num[i] must stop, because the collection has been duplicated. Then we may not be able to exceed the J position when we backtrack from the i+1.
This is not smart, in fact, we should not keep the position of a number before each number, although this can help us to reduce the distance back, but think about, in the i+1 position can backtrack distance, not just and the first position can be traced back to the distance?
Let's take a look at the idea, assuming we've got a number before, and we've got a solution (a foothold for dynamic planning), then when you add the i+1 number, the solution can be obtained by asking F (i+1) (which contains the interval number of the i+1 number), which is actually Is the length of the longest magical space that contains the first i+1 number. And this length, in fact, is the length of the longest magical space that contains the number I, plus 1!
Yes, for F, it is still a dynamic programming problem, but a very simple dynamic programming problem:
F (i+1) =f (i) +1 (3)
But we still have to get mark[num[i+1]], because the previous digit J, which is the same as the first i+1 number, may be contained in the magic interval represented by F (i), and now because the i+1 number is added, J "truncates" f (i).
So for this problem, we don't have to go back (that is, the time complexity is on), just look at the first i+1 number and analyze two things:
The longest space containing the number I numbers does not contain the same number as i+1: Then F (i+1) =f (i) +1
otherwise F (i+1) = I+1-j.
Note the variable names in the article do not correspond exactly to the program. The means of implementation of the program may be more abstract, but the idea is described above.
Code to the king.
#include <iostream> #include <algorithm>using namespace Std;int num[1000001];int limit[1000001];int max_[1000001]; int main () {int i,j,n,t; scanf ("%d", &t);//Scanf_ (T); while (t--) {scanf ("%d", &n); Scanf_ (n); memset (max_,-1,sizeof (max_)); for (i=0;i<n;i++) {scanf ("%d", &num[i]); Scanf_ (Num[i]); } int sum=1; max_[num[0]]=0; limit[0]=0; for (i=1;i<n;i++) {if (max_[num[i]]<limit[i-1]) {sum+= (i-limit[i -1]+1); LIMIT[I]=LIMIT[I-1]; } else {sum+=i-max_[num[i]]; limit[i]=max_[num[i]]+1; } max_[num[i]]=i; } printf ("%d\n", sum); }}
Dynamic programming solution does not contain the number of substrings of the same number