CodeForces 1043D Mysterious Crime 区间合并
题目大意:
给出m个1-n的全排列,问这m个全排列中有几个公共子串。
思路:
首先单个的数字先计算到答案中,有n个。
然后考虑多个数字,如果有两个数字相邻,那么在m个串中必定都能找到这两个数字并且位置相邻。那么我们枚举1-n所有的数字,比如先枚举p1是1,那p2就是在全排列1中p1后面的数字,然后往下面找,看看下面的全排列,p2是不是也在p1的后面,如果是的话,再看p3是不是在p2的后面。
要注意的是,如果我们发现p2在p1的后面,那么我们就把p1p2连起来,合并到dp[1][p1]中(实际上最好用p1的位置当成第二维参数),并且标记一下,下次如果找到了一个被标记过的数字,我们就可以直接把
dp[1][p1]*dp[1][p2]累加到答案中,p2后面的片段就不需要再次扫描了。
时间复杂度的话,每个元素最多和后面连一次,和前面连一次,所以最多被扫两次(实际上应该是1次,因为这个两次重复计算了,要除以2)。也就是说时间复杂度是O(nm)级别的。
//#pragma comment(linker,"/STACK:102400000,102400000") #include<cstdio> #include<algorithm> #include<iostream> #include<vector> #include<map> #include<set> #include<cstring> #include<cmath> #include<queue> #include<stack> #include<stdlib.h> //#include<unordered_map> #define lson l,mid,rt<<1 #define rson mid+1,r,(rt<<1)|1 #define CLR(a,b) memset(a,b,sizeof(a)) #define mkp(a,b) make_pair(a,b) typedef long long ll; using namespace std; inline ll read() { ll x=0,f=1; char ch=getchar(); while(ch<'0'||ch>'9') { if(ch=='-')f=-1; ch=getchar(); } while(ch>='0'&&ch<='9') { x=x*10+ch-'0'; ch=getchar(); } return x*f; } const int maxn=1e5+10; int a[11][maxn],pos[11][maxn],n,m; ll dp[11][maxn]; bool vis[maxn]; ll ans; int main() { n=read(),m=read(); for(int i=1; i<=m; i++) { for(int j=1; j<=n; j++) { a[i][j]=read(); pos[i][a[i][j]]=j; dp[i][j]=1; } } ans=n; int flag; for(int i=1; i<=n; i++) { int temp=pos[1][i];//第一个指针 if(vis[temp])continue; vis[temp]=1; int p1=i; //前元素 if(temp==n) { continue; } int temp2=temp+1; int p2=a[1][temp2];//后元素 flag=1; while(flag) { for(int k=2; k<=m; k++) { int xx=pos[k][p1]; if(a[k][xx+1]==p2)continue; flag=0; break; } if(flag) { if(vis[temp2]==1) { //已经访问过 ans+=(ll)dp[1][temp]*dp[1][temp2]; dp[1][temp]+=dp[1][temp2]; flag=0; } else { ans+=(ll)dp[1][temp]*dp[1][temp2]; dp[1][temp]+=dp[1][temp2]; p1=p2; vis[temp2]=1; temp2++; if(temp2>n)break; p2=a[1][temp2]; } } // printf("temp1:%d temp2:%d\n",temp,temp2); } } printf("%lld\n",ans); }
Acingel is a small town. There was only one doctor here — Miss Ada. She was very friendly and nobody has ever said something bad about her, so who could've expected that Ada will be found dead in her house? Mr Gawry, world-famous detective, is appointed to find the criminal. He asked mm neighbours of Ada about clients who have visited her in that unlucky day. Let's number the clients from 11 to nn. Each neighbour's testimony is a permutation of these numbers, which describes the order in which clients have been seen by the asked neighbour.
However, some facts are very suspicious – how it is that, according to some of given permutations, some client has been seen in the morning, while in others he has been seen in the evening? "In the morning some of neighbours must have been sleeping!" — thinks Gawry — "and in the evening there's been too dark to see somebody's face...". Now he wants to delete some prefix and some suffix (both prefix and suffix can be empty) in each permutation, so that they'll be non-empty and equal to each other after that — some of the potential criminals may disappear, but the testimony won't stand in contradiction to each other.
In how many ways he can do it? Two ways are called different if the remaining common part is different.
The first line contains two integers nn and mm (1≤n≤1000001≤n≤100000, 1≤m≤101≤m≤10) — the number of suspects and the number of asked neighbors.
Each of the next mm lines contains nn integers a1,a2,…,ana1,a2,…,an (1≤ai≤n1≤ai≤n). It is guaranteed that these integers form a correct permutation (that is, each number from 11 to nn appears exactly once).
Output a single integer denoting the number of ways to delete some prefix and some suffix of each permutation (possibly empty), such that the remaining parts will be equal and non-empty.
3 2
1 2 3
2 3 1
4
5 6
1 2 3 4 5
2 3 1 4 5
3 4 5 1 2
3 5 4 2 1
2 3 5 4 1
1 2 3 4 5
5
2 2
1 2
2 1
2
In the first example, all possible common parts are [1][1], [2][2], [3][3] and [2,3][2,3].
In the second and third examples, you can only leave common parts of length 11.