第一题是 EllysSki 。
题意:给n个数,求两个方向的最长递减区间。
可以O(n)。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<cstdio> #include<cstring> #include<algorithm> #include<vector> using namespace std; int Mx(int a,int b){return a>b?a:b;} class EllysSki{ public: int getMax(vector <int> height); }; int EllysSki::getMax(vector <int> height) { int n=height.size(),ans=0; for(int i=0;i<n;i++) { int j=i; while(j+1<n&&height[j+1]<=height[j]) j++; ans=Mx(ans,j-i+1); i=j; } for(int i=n-1;i>=0;i--) { int j=i; while(j&&height[j-1]<=height[j]) j--; ans=Mx(ans,i-j+1); i=j; } return ans; }
第二题是 EllysTeleport 。
题意:连边,找最长链。
自己写了tarjan,没调出来。其实 n2 暴力也行。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<cstdio> #include<cstring> #include<algorithm> #define ll long long using namespace std; int Mx(int a,int b){return a>b?a:b;} int Mn(int a,int b){return a<b?a:b;} const int N=1e4+5; int n,h[N],to[N]; bool vis[N]; class EllysTeleport{ int fnd(int x) { int l=1,r=n,ret=0; while(l<=r) { int mid=l+r>>1; if(h[mid]<=x)ret=mid,l=mid+1; else r=mid-1; } return ret; } public: int getMax(int N, int H1, int A, int B, int P, int Q, int M) { n=N; h[1]=H1; for(int i=2;i<=n;i++) h[i]=((ll)h[i-1]*A+B)%M; sort(h+1,h+n+1); for(int i=1;i<=n;i++) { int d=((ll)h[i]*P+Q)%M; to[i]=fnd(d); } int ans=0; for(int i=1;i<=n;i++) { memset(vis,0,sizeof vis); int cnt=1,cr=to[i]; vis[i]=1; while(cr&&!vis[cr]) { cnt++;vis[cr]=1;cr=to[cr]; } ans=Mx(ans,cnt); } return ans; } };
第三题是 EllysPearls 。
题意:n(<=50) 个球排成一排,每个球是 m(<=15) 种颜色之一。一次操作可以拿出序列中任意一个球,再插进序列的任意一个位置。求最少操作次数使得相同颜色的球是一个区间。
题解:https://www.topcoder.com/blog/2019-topcoder-open-algorithm-round-1b-editorials/
颜色只有 15 ,考虑状压。 1 表示该颜色之前已经确定了一个位置,即当前球必须取出、融入之前自己颜色的区间。
特殊情况就是当前球不动,就能合法;所以再记目前最后的颜色是什么(可以是空)。
还可能遇到当前球,但是把它放在后面,即尚不确定当前颜色。发现这种情况和“融入之前自己颜色的区间”都是要花费1的代价,并且不改变状压的状态。
所以 dp[ i ][ j ][ s ] 表示前 i 个、末尾颜色是 j 、已经确定位置的颜色集合是 s ,即可转移。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<cstdio> #include<cstring> #include<algorithm> #include<vector> using namespace std; const int N=55,K=20,M=(1<<15)+5; int n,m,a[N],bin[K],dp[2][K][M]; class EllysPearls{ void cz(int &x,int y){if(y<x)x=y;} public: int getMin(int tN, int tM, vector <int> pearls) { n=tN; m=tM; for(int i=0;i<n;i++)a[i+1]=pearls[i]; bin[0]=1;for(int i=1;i<=m;i++)bin[i]=bin[i-1]<<1; memset(dp[1],0x3f,sizeof dp[1]); dp[1][0][0]=0; bool u=1,v=0; for(int i=1;i<=n;i++,swap(u,v)) { memset(dp[v],0x3f,sizeof dp[v]); for(int j=0;j<=m;j++) for(int s=0;s<bin[m];s++)//[m]not[n] { int tp=dp[u][j][s]; if(tp>N)continue; int d=bin[a[i]-1]; cz(dp[v][j][s],tp+1); if(!j||j==a[i]) cz(dp[v][a[i]][s|d],tp); if(!(s&d)) cz(dp[v][a[i]][s|d],tp); } } int ans=N; for(int j=0;j<=m;j++) for(int s=0;s<bin[m];s++) cz(ans,dp[u][j][s]); return ans; } };